zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    lda spark 代码官方文档
    4.17 斐波那契数列 K维斐波那契数列 矩阵乘法 构造
    CF R 635 div1 C Kaavi and Magic Spell 区间dp
    CF R 635 div2 1337D Xenia and Colorful Gems 贪心 二分 双指针
    luogu P5043 【模板】树同构 hash 最小表示法
    CF R 633 div 1 1338 C. Perfect Triples 打表找规律
    CF 633 div1 1338 B. Edge Weight Assignment 构造
    4.15 省选模拟赛 哈密顿回路 折半搜索 双指针
    4.15 省选模拟赛 编码 trie树 前缀和优化建图 2-sat
    4.13 省选模拟赛 守卫 点分治 虚树
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476866.html
Copyright © 2011-2022 走看看