题意:给你三个数字N,M,K,给你个N*M的矩阵,对于[i][j]位置的值为i*j,问第K小的数字为多少?
思路:因为第K小得数字一定小于K,我们可以枚举答案这个数字ans从1-K,然后对于每一个ans算出来小于等于的ans数字有多少个(这里不必用N方的,因为每一行是倍增的,所以对于第i行,ans/i就等于这一行小于ans的个数,这个个数不能比这一行数字的总数还多,也就是列数M,这两个值取较小的就行了),如果N^2肯定超时,所以得要个得算法。我们可以发现ans变大小于等于他的数字总数字就多,ans变小小于等于他的数字就少,符合二分的条件,所以我们用二分的方法去寻找ans就行了,这样复杂度正好为。
注意:如这组样例:2 28 49
你会发现42 43都是满足要求的,但是矩阵中没有43这个数字,所以42才是正确答案。我们只要找个下界就可以解决这个问题了。因为这种情况只可能是一个一个非素数,一个素数,且非素数<素数,而这个非素数一定存在在矩阵中。如果非素数>素数,那么小于等于这个非素数的数字个数一定大于小于等于这个素数的数字个数。所以我们求个下界就可以。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5e3 + 5;
long long N,M,K;
long long check(long long m)
{
long long sum = 0;
for(long long i = 1; i <= m && i <= N; i++)//每一行有多少个小于等于m的数字
{
sum += min(m / i,M);
}
return sum;
}
int main()
{
while(~scanf("%lld%lld%lld",&N,&M,&K))
{
long long l = 1,r = K,m = l + (r - l) / 2,key = K;
while(l < r)
{
if(check(m) < key) l = m + 1;
else r = m;
m = l + (r - l) / 2;
}
printf("%lld\n",m);
}
return 0;
}