codeForces 448D.Multiplication Table (二分+数学)

雨燕双飞 提交于 2020-04-06 13:11:13

题意:给你三个数字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;
}










发布了646 篇原创文章 · 获赞 57 · 访问量 14万+
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!