zoukankan      html  css  js  c++  java
  • 完全平方数(莫比乌斯函数容斥)

    小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而这丝毫不影响他对其他数的热爱。

    这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了小X。小X很开心地收下了。

    然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?

    Solution

    首先可以在外层套上二分答案把问题转化为判定问题。

    问题变成了在1~x中,是否存在mid个数不是完全平方数。

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

    再来分析一波莫比乌斯函数,当i中存在完全平方数时,miu[i]=0,有奇数个质因子时我们应当减一,有偶数个质因子时就加。

    所以我们枚举i,容斥系数就是miu[i].

    Code

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define N 300009
    using namespace std;
    long long  miu[N],div[N],prime[N],n,t;
    inline void kk()
    {
        miu[1]=1;
        for(int i=2;i<=N;++i)
        {
            if(!div[i])
            {
                prime[++prime[0]]=i;
                miu[i]=-1;
            }
            for(int j=1;j<=prime[0]&&prime[j]*i<=N;++j)
            { 
              div[prime[j]*i]=1;
              if(i%prime[j]==0)
              {miu[i*prime[j]]=0;break;}
              else miu[i*prime[j]]=-miu[i];
            }
        }
    }
    long long find(long long x)
    {
        long long ll=sqrt(x),ans=0;
        for(int i=1;i<=ll;++i)
          ans+=miu[i]*x/(i*i);
        return ans;
    }
    long long work(long long x)
    {
        long long l=1,r=x<<1,ans=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(find(mid)<x)l=mid+1;
            else
            {
                ans=mid;r=mid-1;
            } 
        } 
        return ans;
    }
    int main()
    {
        cin>>t;
        kk();
        while(t--)
        {
            scanf("%lld",&n);
            printf("%lld
    ",work(n));
        }
        return 0;
    }
  • 相关阅读:
    Vmstat主要关注哪些数据?
    Swap是个什么东东?
    Buffers与cached啥区别
    做错的题目——关于构造器返回值
    做错的题目——this的指向
    JS判断一个数是否为质数
    数组扁平化
    JS实现快速排序
    正则实现千分符
    获取鼠标的当前位置
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9761243.html
Copyright © 2011-2022 走看看