zoukankan      html  css  js  c++  java
  • 【BZOJ2440】[中山市选2011]完全平方数

    题意描述

     原题

      

     一句话描述:

      求第K个不是完全平方数的倍数的数。

      K≤$10^{9}$

    ------------------------------------------

    题解:

      首先,直接求第$k$个不是完全平方数倍数的数不好求,我们不妨将它转换为一个判定问题:对于一个确定的常数$x$,他是不是第k个不是完全平方数倍数的数。这句话等价于:$[1,x]$是否有k个不是完全平方数倍数的数,这个怎么求呢?

      根据容斥原理,答案就是:0个质数乘积的平方的倍数的数量(1的倍数)- 1个质数乘积的平方的倍数的数量(4,9,25的倍数)+ 2个质数乘积的平方的倍数的数量(36,100的倍数)。

      恰好发现,$i^2$对应的符号就是$μ(i)$,所以答案就是

       那么我们二分一下$x$,就能找到答案了。二分的范围是$[1,k*2]$.

      代码实现:

      

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    const int maxn = 1e6+10;
    typedef long long ll;
    int mu[maxn],prime[maxn],vis[maxn];
    void init_mu(int n){
        int cnt=0;
        mu[1]=1;
        for(int i=2;i<n;i++){
            if(!vis[i]){
                prime[cnt++]=i;
                mu[i]=-1;
            }
            for(int j=0;j<cnt&&i*prime[j]<n;j++){
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)   {mu[i*prime[j]]=0;break;}
                else { mu[i*prime[j]]=-mu[i];}
            }
        }
    }
    inline ll find(ll x) {
        ll least = sqrt(x+0.5),ans=0;
        for(register int i=1;i<=least;i++) {
            ans+=mu[i]*x/(1LL*i*i);
        }
        return ans;
    }
    inline ll calc(ll k) {
        ll l = 1,r = k<<1;
        while(l<r) {
            ll mid = (r+l)>>1;
            ll temp = find(mid);
    #ifdef DEBUG
            printf("%d %d %d
    ",l,r,temp);
    #endif
            if(temp<k) l=mid+1;
            else r=mid;
        }
        return r;
    }
    int T;
    ll k;
    int main() {
        init_mu(1000001);
        scanf("%d",&T);
        while(T--) {
            scanf("%lld",&k);
            printf("%lld
    ",calc(k));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    申请奖励加分
    6.14
    6.11
    6.10
    6.9
    6.8
    6.7
    6.6
    6.5
    6.4
  • 原文地址:https://www.cnblogs.com/Syameimaru/p/9307259.html
Copyright © 2011-2022 走看看