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

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值