zoukankan      html  css  js  c++  java
  • P2257 YY的GCD(莫比乌斯反演)

    第一次做莫比乌斯反演,推式子真是快乐的很啊(棒读)

    前置

    若函数(F(n))(f(d))存在以下关系

    [ F(n)=sum_{n|d}f(d) ]

    则可以推出

    [ f(n)=sum_{n|d}mu(frac{d}{n})F(d) ]

    这就是莫比乌斯反演

    题目要求

    (gcd(a,b)={prime},ainleft[1,n ight],binleft[1,m ight])

    思路

    根据题意所以设出(f(n))表示(gcd(a,b)=n)(a,b)对数
    根据莫比乌斯反演的形式

    [ F(n)=sum_{n|d}f(d) ]

    可以设出一个函数(F(n)),表示(n|gcd(a,b))((a,b))对数
    因为(n|gcd(a,b)),所以(a=k_1 imes n,b=k_2 imes n)
    所以显然有

    [ F(x)=lfloorfrac{n}{x} floor imeslfloorfrac{m}{x} floor ]

    因为

    [ f(x)=sum_{x|d}mu(frac{d}{x})F(d) ]

    所以

    [ f(x)=sum_{x|d}mu(frac{d}{x}) imeslfloorfrac{n}{d} floor imeslfloorfrac{m}{d} floor ]

    考虑到(frac{d}{n})的形式并不优美,我们换一种东西枚举

    [ f(x)=sum_{t=1}^{lfloorfrac{n}{x} floor}mu(t) imeslfloorfrac{n}{t imes x} floor imeslfloorfrac{m}{t imes x} floor ]

    所以

    [ ans=sum_{xin{prime}}^nf(x)=sum_{xin{prime}}^nsum_{t=1}^{lfloorfrac{n}{x} floor}mu(t) imeslfloorfrac{n}{t imes x} floor imeslfloorfrac{m}{t imes x} floor ]

    这样能拿到50PTS
    然后设(T=t*x),这样形式就变得更优美了一些
    原式变形为

    [ ans=sum_{xin{prime}}^nf(x)=sum_{xin{prime}}^nsum_{t=1}^{lfloorfrac{n}{x} floor}mu(frac{T}{x}) imeslfloorfrac{n}{T} floor imeslfloorfrac{m}{T} floor ]

    [ ans=sum_{xin{prime}}^nf(x)=sum_{T=1}^{min(n,m)}sum_{din{prime},d|T}mu(frac{T}{d}) imeslfloorfrac{n}{T} floor imeslfloorfrac{m}{T} floor ]

    [ ans=sum_{xin{prime}}^nf(x)=sum_{T=1}^{min(n,m)}lfloorfrac{n}{T} floor imeslfloorfrac{m}{T} floor imessum_{din{prime},d|T}mu(frac{T}{d}) ]

    后面(mu)的部分可以前缀和一下
    前面的可以整除分块
    加上线性筛
    然后没了

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    short mu[10001000];
    int n,m,T,iprime[10001000],cnt,isprime[10001000],summu[10001000];
    void prime(int n){
        mu[1]=1;
        isprime[1]=true;
        for(int i=2;i<=n;i++){
            if(!isprime[i])
                iprime[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&iprime[j]*i<=n;j++){
                isprime[iprime[j]*i]=true;
                if(i%iprime[j]==0){
                    mu[iprime[j]*i]=0;
                    break;
                }
                mu[iprime[j]*i]=-mu[i];
            }
        }
        for(int i=1;i<=cnt;i++)
            for(int j=1;j*iprime[i]<=n;j++)
                summu[iprime[i]*j]+=mu[j];
        for(int i=1;i<=n;i++)
            summu[i]+=summu[i-1];
    }
    long long f(int n,int m){
        long long ans=0;
        for(int l=1,r;l<=min(n,m);l=r+1){
            r=min(n/(n/l),m/(m/l));
            ans+=1LL*(summu[r]-summu[l-1])*(n/l)*(m/l);
        }
        return ans;
    }
    int main(){
        prime(10000100);
        scanf("%d",&T);
        while(T--){
            long long ans=0;
            scanf("%d %d",&n,&m);
            if(n<m)
                swap(n,m);
            ans+=f(n,m);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    HA分布式集群二hive配置
    win下写任务提交给集群
    win10下将spark的程序提交给远程集群中运行
    Scala快学笔记(三)
    Scala快学笔记(二)
    Scala快学笔记(一)
    统计学习方法 三 kNN
    统计学习方法 二 感知机
    fluent python(一)
    Codewar (1)
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10065775.html
Copyright © 2011-2022 走看看