• 二分+mu函数实质及应用(原理)!——bzoj2440好题


    首先想到用二分来判断

    不是平方数的倍数,即没有次数>=2的质因子
    显然用容斥原理,即所有答案-1个质因子的平方的所有倍数+2个质因子的所有平方倍...
    等价于对于每个数,如果它有奇数个质因子,那么其贡献系数是-1,反之则是1,

    如果自己本身有平方因子(比如2*2*3),那么其贡献系数是0,因为已经被前面的筛掉了(1的时候+1,2,3的时候-1,2*3的时候+1,最后已经成为0了),根本不用去管它

    那么可以发现i的系数恰好是mu[i]

    其实由这题可以发现mu[i]函数的意义,即容斥系数

    本题用容斥筛出i的倍数时 对应的系数恰好是 mu[i]是因为:mu[i]的本质就是来筛i的倍数的

    设f(n)是原函数,g(n)是和函数

    mu[p1]=-1 是因为 f(n)必须要减去一个g(n/p1)

    mu[p1*p2]=1是因为 f(n)=g(n)-g(n/p1)-g(n/p2),多减掉了一个g(n/p1/p2)

    mu[p1^k*p2]=0 是因为 f(n)=g(n)-g(n/p1)-g(n/p2)+g(n/p1/p2) 里 的g(n/p1^k/p2)已经被做成0了

      g(n/p1的所有倍数)系数-1,g(n/p2的所有倍数)系数-1,g(n/p1/p2)的所有倍数系数+1,所以g(n/p1/p2的所有倍数)的系数最后变成了0,包括g(n/p1/p1/p2)之类的系数

    所以不需要再加减了

    #define N 100000
    using namespace std;
    typedef long long LL;
    const LL inf = (1LL<<31)-1;
    const int MAXN = 100011;
    LL l,r;
    int ans;
    int mobius[MAXN],k;
    int prime[MAXN],cnt;
    bool ok[MAXN];
    
    inline int getint()
    {
        int w=0,q=0; char c=getchar();
        while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
    }
    
    inline void init(){
        mobius[1]=1;
        for(int i=2;i<=N;i++) {
        if(!ok[i]) prime[++cnt]=i,mobius[i]=-1;
        for(int j=1;j<=cnt && prime[j]*i<=N;j++) {
            ok[i*prime[j]]=1;
            if(i%prime[j]) mobius[i*prime[j]]=-mobius[i];
            else { mobius[i*prime[j]]=0; break; }
        }
        }
    }
    
    inline bool check(LL x){
        LL div=sqrt(x); int tot=0;
        for(int i=1;i<=div;i++) {
        tot+=mobius[i] * (x/(i*i));
        }
        //tot=x-tot;
        if(tot>=k) return true;
        return false;
    }
    
    inline void work(){
        init(); int T=getint(); LL mid;
        while(T--) {
        k=getint(); l=1; r=inf; ans=inf;
        while(l<=r) {
            mid=(l+r)/2;
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d
    ",ans);
        }
    }
    
    int main()
    {
        work();
        return 0;
    }
  • 相关阅读:
    2020.9.26
    2020.10.2
    判断方法
    sql与include
    File类的获取方法
    【每日日报】第十五天
    【每日日报】第十三天
    【每日日报】第十四天
    两数相加(输入框)
    判断闰年
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11146559.html
Copyright © 2020-2023  润新知