[bzoj2440]完全平方数(二分+mobius反演)
解题关键:由容斥原理得,num=1的倍数的数量−一个质数平方数(9,25,49...)的倍数的数量+两个质数的积平方数(36,100,225...)的数量−三个质数......
这道题用莫比乌斯的正向函数表达式理解较容易
此题让自己理解了只要与倍数相关即可用mobius。
此题还需要注意的一点,是平方数只需要反演质数。貌似是常识
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 ll t,n; 10 inline ll read(){ 11 char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar()); 12 ll x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0'; 13 if(k=='-')x=0-x;return x; 14 } 15 //莫比乌斯函数线性筛法 16 const int maxn=100000+5; 17 bool vis[maxn]; 18 int prime[maxn],mu[maxn]; 19 void init_mu(int n){ 20 int cnt=0; 21 mu[1]=1; 22 for(int i=2;i<n;i++){ 23 if(!vis[i]){ 24 prime[cnt++]=i; 25 mu[i]=-1; 26 } 27 for(int j=0;j<cnt&&i*prime[j]<n;j++){ 28 vis[i*prime[j]]=1; 29 if(i%prime[j]==0) {mu[i*prime[j]]=0;break;} 30 else { mu[i*prime[j]]=-mu[i];} 31 } 32 } 33 } 34 35 bool check(ll x){ 36 ll ans=0; 37 for(ll i=1;i*i<=x;i++){ 38 ans+=mu[i]*(x/(i*i)); 39 } 40 return ans>=n; 41 } 42 43 ll erfen(ll l,ll r){ 44 while(l<r){ 45 ll mid=(l+r)>>1; 46 if(check(mid)) r=mid; 47 else l=mid+1; 48 } 49 return r; 50 } 51 int main(){ 52 init_mu(100000); 53 t=read(); 54 while(t--){ 55 n=read(); 56 printf("%lld\n",erfen(1, 10000000000)); 57 } 58 59 }