Matrix
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 5724 | Accepted: 1606 |
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
这题一开始我在找规律 以为是满足右上角最小 左下角最大的规律 写了一发能过样例 WA了 所以打比赛的时候要注意不是推的规律尽量别用 然后我们看式子 你固定i ,那么j增大就是递增的,所以你在主函数里一个二分找答案
check函数里面一个二分找比他小的有多少个 注意没有等于
对啦 子函数里面的二分一定要x = 1开始,如果从0开始 ,不然当你x = -1,y = 0的时候会一直是0,可以加一个floor 或者x从1开始 避免了第一次出现负数 死循环
那么我这里给出一种解决方法 :
二分时如果l或r出现负数,最好直接向下取整,否则如(-1+0)/2=0,本来是想让他等于-1的,这样就可能进入死循环。
LL mid=(LL)(floor((l+r)/2.0+eps));
然后就行啦 第一个二分套二分题
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define dbg(x) cout<<#x<<" = "<< (x)<< endl long long cal(int i,int j){ return i*1LL*i+100000*1LL*i+j*1LL*j-100000*1LL*j+i*1LL*j; } int n; long long m; long long check(long long mid){ long long sum = 0; for(int i=1;i<=n;++i){ int x = 1,y=n; while(x<=y){ int mid_new = (x+y)>>1; if(cal(mid_new,i)>mid) y = mid_new - 1; else x = mid_new +1; } sum+=y; } return sum; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%lld",&n,&m); long long l = -10000000000000,r=10000000000000; while(l<=r){ long long mid = l+(r-l)/2; long long v = check(mid); if(v>=m) r = mid -1; else l = mid +1; } printf("%lld\n",l); } return 0; }