poj 3685
/*給定n,有n*n個數,有aij=i * i + m * i + j * j - m * j + i * jn <= 50000m <= 100000求所有aij中第m大的數還是二分答案,先根據生成的式子,求出最大的和最小的數字,然后二分答案,驗證我們發現,對于同列的數字,按照行數的增加,數字大小是遞增的根據這個性質,就很容易驗證是否存在>=n*n-m+1個數字>=val了看了題一下子就有想法了,結果卻wa了一天...原因在于自作聰明地進行數學推論然后非要從同行中進行二分...最后才發現不滿足遞減性質...不過最后ac的時候還是很爽快的
*/
#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的數字的個數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的數量range(c,1,n){ans += findK(c,val);}return ans >= (ll)n*n - M+1;//必須要有>=n*n-M+1的數量>=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;
}
?
轉載于:https://www.cnblogs.com/dandi/p/4077344.html
總結
- 上一篇: c#调用本地命令并截取Output
- 下一篇: 简单的beego分页功能代码