• 【bzoj2820】YY的GCD【莫比乌斯反演】


    题目传送门
    题意: 给定n,m,求1xn,1ymgcd(x,y)为质数的(x,y)有多少对。
    题解:我们考虑枚举每一个质数p,则
    i=1nj=1m(gcd(i,j)==p)
    可以转化为
    i=1npj=1mp(gcd(i,j)==1)
    我们令F(i)表示gcd是i的倍数的数对的个数。则F(i)=npimpi
    我们令f(i)表示gcd是i的数对的个数。则F(i)=i|df(d)。我们的目标是要求出f(1)。
    运用莫比乌斯反演可得
    f(i)=i|dμ(di)F(d)
    =>f(i)=i|dμ(di)npdmpd
    由于i=1
    =>ans=pd=1npμ(d)npdmpd
    注意到,这个东西是可以分块优化的,单次计算时间直接降到根号级别。
    但是这样还是远远不够的,会超时。
    于是,我们可以变一下式子,枚举pd的值。
    ans=t=2ntmtp|tμ(tp)
    如果能快速地求出p|tμ(tp)对于任意t的值就好了。我们可以预处理一下,枚举每一个质数,去累加它的倍数的答案。这样我们的时间复杂度大约为pnp,这个东西大约是O(n)的,有兴趣可以自行查阅相关资料:质数的个数与质数的倒数和。
    我们求一个前缀和,再带人莫比乌斯反演进行分块求和即可。
    综上,我们做到了O(n+Tn)解决本题。其实代码很短也很简单。
    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=10000005;
    int t,n,m,p[N/10],miu[N],sum[N];
    bool vis[N];
    long long calc(int n,int m){
        if(n>m){
            swap(n,m);
        }
        int last;
        long long ans=0;
        for(int i=2;i<=n;i=last+1){
            last=min(n/(n/i),m/(m/i));
            ans+=1LL*(n/i)*(m/i)*(sum[last]-sum[i-1]);
        }
        return ans;
    }
    int main(){
        miu[1]=1;
        for(int i=2;i<=10000000;i++){
            if(!vis[i]){
                p[++p[0]]=i;
                miu[i]=-1;
            }
            for(int j=1;j<=p[0]&&i*p[j]<=10000000;j++){
                vis[i*p[j]]=true;
                if(i%p[j]){
                    miu[i*p[j]]=-miu[i];
                }else{
                    break;
                }
            }
        }
        for(int i=1;i<=p[0];i++){
            for(int j=1;p[i]*j<=10000000;j++){
                sum[p[i]*j]+=miu[j];
            }
        }
        for(int i=3;i<=10000000;i++){
            sum[i]+=sum[i-1];
        }
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            printf("%lld
    ",calc(n,m));
        }
        return 0;
    }
  • 相关阅读:
    学习方法与经验总结
    工具综合症?资料收集狂?
    SpringMVC 过滤器Filter使用解析
    Spring 管理Filter和Servlet
    pom.xml配置详解
    开发Java web应用程序的介绍
    java web构建学习(概念基础)
    题目1474:矩阵幂
    题目1473:二进制数
    Python strip()方法
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476866.html
Copyright © 2020-2023  润新知