【bzoj2440】完全平方数

题意:

求第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\n",getans(n));
43     }
44 }
View Code

posted @ 2013-10-21 19:33  g_word  阅读(2183)  评论(1编辑  收藏  举报