【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

你可能感兴趣的:(ZOJ)