题意:
求第n个不为完全平方数倍数的数
题解:
网上有人说答案不会超过2n (求证0 0?) 竟然不超过2n 那么很明显就是用二分做了
二分判定就是要求小于等于n的合法的数的个数
不难发现一个数若为完全平方数的倍数 则他的质因子肯定有一个的指数大于1
那么合法的数的所有质因数质数肯定都为1
_________________________________________________________________________________
于是题目变为 求小于等于的质因数指数都为1的数的个数
我们可以把<=n的 所有i^2的倍数的数减掉(i为质数)
算重?
莫比乌斯函数!(容斥原理- -)
答案就是n-奇数个质数的平方的倍数的个数+偶数个质数的平方的倍数的个数
即 ans=Σmiu[i]*(n/i^2) (i<=(int) sqrt(n) 显然i如果>sqrt(n)个数肯定为0)
1 (i为奇数个质数的乘积)
miu[i]= -1 (i为偶数个质数的乘积)
0 (i有某个质数指数>1)
_________________________________________________________________________________
代码:
1 #include <cstdio> 2 #include <cmath> 3 typedef long long ll; 4 const ll M=100001; 5 ll t,n,miu[M],pri[M],bo[M],ans; 6 void makemiu(){ 7 miu[1]=1; 8 for (ll i=2;i<M;i++){ 9 if (!bo[i]){ 10 pri[++pri[0]]=i; 11 miu[i]=-1; 12 } 13 for (ll j=1;j<=pri[0] && pri[j]*i<M;j++){ 14 bo[i*pri[j]]=1; 15 if (i%pri[j]==0){ 16 miu[i*pri[j]]=0; 17 break; 18 }else miu[i*pri[j]]=-miu[i]; 19 } 20 } 21 } 22 ll check(ll t){ 23 ll sq=(int)sqrt(t),res=0; 24 for (ll i=1;i<=sq;i++) 25 res=res+miu[i]*(t/(i*i)); 26 return res; 27 } 28 ll getans(ll t){ 29 ll l=0,r=t*2,mid; 30 while (l+1<r){ 31 mid=(l+r)/2; 32 if (check(mid)<t) l=mid; 33 else r=mid; 34 } 35 return r; 36 } 37 int main(){ 38 scanf("%I64d",&t); 39 makemiu(); 40 for (ll i=1;i<=t;i++){ 41 scanf("%I64d",&n); 42 printf("%I64d ",getans(n)); 43 } 44 }