[洛谷P4318]完全平方数

题意

求自然数中,第\(k\)个不含平方因子的数

思路

这道题的做法还挺多的(打表,二分,反演...)

我用的做法是二分+容斥

显然答案满足二分性,假设当前检验的数为\(n\)

没有平方因子的数=所有数-一个质数平方的因子的倍数+两个质数乘积平方的倍数-三个的.......

对于一个数\(i^2\),可以发现\(\mu (i)\)就是\(i^2\)在上面那个式子中的系数,所以上式可以表示为$$ans=\sum_{i=1}{i2\leq n}{\mu (i)\times \frac{n}{i^2}}$$

一遍\(check\)\(\sqrt {n}\),所以整个算法复杂度为\(O(logn\sqrt {n})\)

Code

#include<bits/stdc++.h>
#define N 50005
using namespace std;
typedef long long ll;
int T;
int p[N],mu[N],cnt;
ll k;
bool isnotp[N];

template <class T>
void read(T &x)
{
	char c;int sign=1;
	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
	while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}

void init(int maxn)
{
	isnotp[1]=1;
	mu[1]=1;
	for(int i=2;i<=maxn;++i)
	{
		if(!isnotp[i]) p[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&(ll)p[j]*i<=maxn;++j)
		{
			isnotp[p[j]*i]=1;
			if(i%p[j]==0)
			{
				mu[i*p[j]]=0;
				break;
			}
			else mu[i*p[j]]=-mu[i];
		}
	}
}
bool check(ll x)//[1,x]>=k ?
{
	ll ret=0;
	for(ll i=1;i*i<=x;++i) ret+=mu[i]*(x/(i*i));
	return ret>=k;
}

int main()
{
	read(T);
	init(N-5);
	while(T--)
	{
		ll l=1,r=5000000000LL,ans=0;
		read(k);
		while(l<=r)
		{
			ll mid=(l+r)>>1;
			if(check(mid)) r=mid-1,ans=mid;
			else l=mid+1;
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2019-10-24 10:34  擅长平地摔的艾拉酱  阅读(101)  评论(0编辑  收藏  举报
/*取消选中*/