POJ 3685
Matrix
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 4428 | Accepted: 1102 |
Description
Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix.
Input
The first line of input is the number of test case.
For each test case there is only one line contains two integers, N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N). There is a blank line before each test case.
Output
For each test case output the answer on a single line.
Sample Input
12 1 1 2 1 2 2 2 3 2 4 3 1 3 2 3 8 3 9 5 1 5 25 5 10
Sample Output
3 -99993 3 12 100007 -199987 -99993 100019 200013 -399969 400031 -99939
Source
POJ Founder Monthly Contest – 2008.08.31, windy7926778
首先二分第m小的数,由公式易得每列的数是按照从小到大排列的,因此可二分,两次二分即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 8 typedef long long ll; 9 10 int n; 11 ll m; 12 13 ll cal(ll i,ll j) { 14 return i * i + j * j + (i - j) * 100000 + i * j; 15 } 16 17 bool judge(ll x) { 18 ll sum = 0; 19 for(int j = 1; j <= n; ++j) { 20 int l = 0,r = n; 21 while(l < r){ 22 int mid = (l + r + 1) / 2; 23 if(cal(mid,j) <= x) { 24 l = mid; 25 } else { 26 r = mid - 1; 27 } 28 } 29 sum += l; 30 } 31 32 return sum >= m; 33 34 } 35 36 void solve() { 37 ll l = -1e12,r = 1e12; 38 39 //printf(" n = %d l = %lld r = %lld\n",n,l,r); 40 41 while(l < r) { 42 ll mid = (l + r) >> 1; 43 if(judge(mid)) r = mid; 44 else l = mid + 1; 45 } 46 47 48 49 printf("%I64d\n",l); 50 } 51 52 int main() { 53 // freopen("sw.in","r",stdin); 54 55 int t; 56 scanf("%d",&t); 57 58 while(t--) { 59 scanf("%d%I64d",&n,&m); 60 solve(); 61 } 62 63 return 0; 64 }