【BZOJ2440&&2986】完全平方数
题意:求第k个无平方因子数是多少
无平方因子数(square-free number),即质因数分解之后所有质因数的次数都为1的数
膜拜Po姐姐
二分答案 设二分后值为x 我们考虑前x个数中是否含有超过k个不是平方因子的数
我们考虑平方因子一定含有至少一个质数的平方
那么考虑容斥,即质数平方个数为0的数的个数-质数平方个数为1的数的个数+质数平方个数为2的数的个数-……
公式表示的话 设有p个素数而且选择了i个素数是平方,且任选i个素数的乘积为d,得到公式
$f(x)=\sum_{i=0}^{p}(-1)^i \lfloor \frac{n}{d^{2}} \rfloor(d为任意i个素数相乘的积)$
发现d最多选择到$\sqrt{ n }$ 那么我们可以考虑直接枚举d 于是问题变成了如何快速判断d的贡献
莫比乌斯函数即是。
然后根据莫比乌斯函数的定义式,将式子化为$f(x)=\sum_{d=1}^{\sqrt{x}} \mu (d) \lfloor \frac{n}{d^{2}} \rfloor $
所以我们枚举根号n内的所有答案 带入计算即可 复杂度$O(\sqrt{n}log{n})$
/*To The End Of The Galaxy*/ #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<iomanip> #include<bitset> #include<stack> #include<map> #include<set> #include<cmath> #include<complex> #define debug(x) cerr<<#x<<"="<<x<<endl #define INF 0x7f7f7f7f #define llINF 0x7fffffffffffll #define P(x,y) (((x-1)*c)+y) using namespace std; typedef pair<int,int> pii; typedef long long ll; inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } inline long long llinit() { long long now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } int n=100000,prime[100005],cnt,mu[100005]; bool vis[100005]; void getmu() { mu[1]=1; for(int i=2;i<=n;i++) { if(!vis[i]) { vis[i]=1; mu[i]=-1; ++cnt;prime[cnt]=i; } for(int j=1;j<=cnt&&prime[j]*i<=n;j++) { vis[i*prime[j]]=1; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } } #define mid ((l+r)>>1) int cas; ll l,r; ll calc(ll x) { ll res=0; for(int i=1;i*i<=x;i++) { res+=x/(i*i)*mu[i]; } return res; } int main() { cas=init(); getmu(); int k; ll ans; for(int i=1;i<=cas;i++) { k=init(); l=1,r=k*2; while(l<=r) { if(calc(mid)>=k) { ans=mid; r=mid-1; } else l=mid+1; } printf("%lld\n",ans); } return 0; }