poj 3685
/*給定n,有n*n個(gè)數(shù),有aij=i * i + m * i + j * j - m * j + i * jn <= 50000m <= 100000求所有aij中第m大的數(shù)還是二分答案,先根據(jù)生成的式子,求出最大的和最小的數(shù)字,然后二分答案,驗(yàn)證我們發(fā)現(xiàn),對(duì)于同列的數(shù)字,按照行數(shù)的增加,數(shù)字大小是遞增的根據(jù)這個(gè)性質(zhì),就很容易驗(yàn)證是否存在>=n*n-m+1個(gè)數(shù)字>=val了看了題一下子就有想法了,結(jié)果卻wa了一天...原因在于自作聰明地進(jìn)行數(shù)學(xué)推論然后非要從同行中進(jìn)行二分...最后才發(fā)現(xiàn)不滿足遞減性質(zhì)...不過(guò)最后ac的時(shí)候還是很爽快的
*/
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define range(i,a,b) for (long long i=a;i<=b;i++)using namespace std;typedef long long ll;const ll m = 1e5;ll n;
ll M;inline ll Int(ll i,ll j)
{return i * i + m * i + j * j - m * j + i * j;
}//找到最小的i,滿足>=val
ll findK(ll j,ll val)
{ll l(1),r(n);while(l+1<r){int mid = (l+r)>>1;if (Int(mid,j) >= val)r = mid;elsel = mid;}//返回>=val的數(shù)字的個(gè)數(shù)if (Int(l,j) >= val)return n-l+1;if (Int(r,j) >= val)return n-r+1;return 0;
}bool test(ll val)
{ll ans(0);//返回每一行的>=val的數(shù)量range(c,1,n){ans += findK(c,val);}return ans >= (ll)n*n - M+1;//必須要有>=n*n-M+1的數(shù)量>=ans,ans才有可能是答案
}int main()
{int t;cin>>t;range(c,1,t){cin>>n>>M;ll l(-n*m),r(n*n*3 + n*m);while(l+1<r){ll mid = (l+r)/2;if (mid == 5101786214){cout<<"";}if (test(mid)){l = mid;}else{r = mid;}}if (test(r)){cout<<r<<endl;}if (test(l)){cout<<l<<endl;}}return 0;
}
?
轉(zhuǎn)載于:https://www.cnblogs.com/dandi/p/4077344.html
總結(jié)
- 上一篇: c#调用本地命令并截取Output
- 下一篇: 简单的beego分页功能代码