P4318 完全平方数

洛谷P4318 完全平方数

f ( n ) f(n) f(n)表示在 1 1 1 n n n中小X不讨厌的数的数量。显然 f ( n ) f(n) f(n)是单调递增的,所以我们可以二分答案。

根据容斥原理可得

f ( n ) = n f(n)=n f(n)=n以内所有数的数量 − n -n n以内每个质数的平方的倍数的数量 + n +n +n以内每两个质数的平方的倍数的数量 − ⋯ -\cdots

我们发现每个部分的正负与莫比乌斯函数有关系,可变为

f ( n ) = ∑ i = 1 n μ ( i ) × ⌊ n i 2 ⌋ f(n)=\sum\limits_{i=1}^{\sqrt n}\mu(i)\times \lfloor \dfrac{n}{i^2}\rfloor f(n)=i=1n μ(i)×i2n

二分求得使 f ( n ) = k f(n)=k f(n)=k n n n值即可。时间复杂度为 O ( T w log ⁡ w ) O(T\sqrt w\log w) O(Tw logw),其中 w w w为二分的范围。

code

#include<bits/stdc++.h>
using namespace std;
int t,k,z[100005],p[100005],mu[100005];
long long check(long long g){
	long long re=0;
	for(int i=1;i*i<=g;i++){
		re=re+mu[i]*(g/i/i);
	}
	return re;
}
int main()
{
	mu[1]=1;
	for(int i=2;i<=100000;i++){
		if(!z[i]){
			p[++p[0]]=i;mu[i]=-1;
		}
		for(int j=1;j<=p[0]&&i*p[j]<=100000;j++){
			z[i*p[j]]=1;
			if(i%p[j]==0){
				mu[i*p[j]]=0;
				break;
			}
			mu[i*p[j]]=-mu[i];
		}
	}
	scanf("%d",&t);
	while(t--){
		scanf("%d",&k);
		long long l=1,r=2e9,mid,vt;
		while(l<=r){
			mid=(l+r)/2;
			vt=check(mid);
			if(vt<k) l=mid+1;
			else r=mid-1;
		}
		printf("%lld\n",r+1);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值