• UVA11426 GCD


    UVA11426 GCD - Extreme (II)

    题目描述

    PDF

    输入输出格式

    输入格式:

    输出格式:

    输入输出样例

    输入样例#1:

    10
    100
    200000
    0

    输出样例#1:

    67
    13015
    143295493160

    Solution

    这道题我用莫比乌斯反演和欧拉函数都写了一遍,发现欧拉函数比莫比乌斯反演优秀?

    求所有(gcd=k)的数对的个数,记作(f[k],ans=sum_{i=1}^{n}(f[i]-1)),为什么还要-1,我们注意到(j=i+1),自己与自己是不算的,再乘上这个数的大小(k)就可以了

    我们发现要求(sum_{i=1}^{n-1}sum_{j=i+1}^{n}{gcd(i,j)}),我们令(gcd(i,j)=k),则必有(gcd(a imes k,b imes k)=k o gcd(a,b)=1),我们枚举这两个数中大的那个,另一个数就有(phi[i](1<=i <=n/k))个,所以(f[n]=sum_{i=1}^{n/k}phi(i))

    筛一下欧拉函数求前缀和就可以了

    那么?莫比乌斯反演怎么写呢?
    (ans=sum_{i=1}^{n-1}sum_{j=i+1}^{n}gcd(i,j))
    (ans=sum_{i=1}^{n}sum_{j=1}^{n}gcd(i,j))

    我么观察这两个式子的区别,一个是从j从1开始,另一个是从i+1开始,这两个式子是具有几何意义的,上面的式子求得是一个三角形的答案(且不包括对角线),下面的是矩形.那么我们用下面的式子-对角线上的答案再除以2就是上面的答案了

    (对角线上的答案就是(gcd(i,i)=i),所以一个等比数列求和就好了)

    下面的式子很好反演,套路套路....

    [sum_{d=1}^{n}dsum_{i=1}^{n}sum_{j=1}^{n}[gcd(i,j)==d] ]

    [sum_{d=1}^{n}dsum_{p=1,p|i,p|j}^{lfloorfrac{n}{d} floor}mu(p) lfloorfrac{n}{d imes p} floorlfloorfrac{n}{d imes p} floor ]

    线性筛莫比乌斯函数,然后套个整除分块就好了(还是没有第一种方法快,如果莫比乌斯反演有比博主还快的方法,请告知我)

    Code1

    #include<bits/stdc++.h>
    #define lol long long
    #define il inline
    #define rg register
    #define Min(a,b) (a)<(b)?(a):(b)
    #define Max(a,b) (a)>(b)?(a):(b)
    #define NN 4000000
    
    using namespace std;
    
    const int N=4e6+10;
    int n,tot;
    lol phi[N],prime[N];
    bool vis[N];
    
    il void init() {
        phi[1]=1;
        for(rg int i=2;i<=NN;i++) {
            if(!vis[i]) prime[++tot]=i,phi[i]=i-1;
            for(rg int j=1;j<=tot && i*prime[j]<=NN;j++) {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0) {
                    phi[i*prime[j]]=phi[i]*prime[j];
                }
                else phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
        for(rg int i=1;i<=NN;i++) phi[i]+=phi[i-1];
    }
    int main()
    {
        ios::sync_with_stdio(0);
        init();
        while(cin>>n) {
            lol ans=0;
            if(n==0) break;
            for(rg int i=1;i<=n;i++) ans+=1ll*(phi[n/i]-1)*i;
            cout<<ans<<endl;
        }
    }
    

    Code2

    #include<bits/stdc++.h>
    #define in(i) (i=read())
    #define il extern inline
    #define rg register
    #define mid ((l+r)>>1)
    #define ll(x) (x<<1)
    #define rr(x) (x<<1|1)
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define lol __int128
    using namespace std;
    
    const lol N=4e6+10;
    
    lol read() {
        lol ans=0, f=1; char i=getchar();
        while (i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while (i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48), i=getchar();
        return ans*f;
    }
    
    lol cnt;
    lol vis[N]={0,1},prime[N],mu[N]={0,1};
    
    void init() {
        for (lol i=2;i<=N-10;i++) {
            if(!vis[i]) prime[++cnt]=i,mu[i]=-1;
            for (lol j=1;j<=cnt && prime[j]*i<=N-10;j++) {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0) break;
                mu[i*prime[j]]=-mu[i];
            }
        }for (lol i=1;i<=N-10;i++) mu[i]+=mu[i-1];
    }
    
    lol work(lol d,lol n,lol ans=0) {
        n/=d;
        for (lol l=1,r;l<=n;l=r+1) {
            r=n/(n/l);
            ans+=(mu[r]-mu[l-1])*(n/l)*(n/l);
        }return ans;
    }
    
    int main()
    {
        long long ans,n; init();
        while(scanf("%lld",&n)==1 && n) {
            ans=0;
            for (lol i=1;i<=n;i++) ans+=i*work(i,n);
            printf("%lld
    ",(ans-(n+1)*n/2)/2);
        }
        return 0;
    }
    
  • 相关阅读:
    sql 行转列
    wm_concat函数 用法
    PL/SQL如何调试Oracle存储过程
    Oracle&SQLServer中实现跨库查询
    Oracle 中 decode 函数用法
    Oracle中给用户赋予debug权限
    Oracle中的NVL函数
    oracle 触发器 pragma autonomous_transaction
    ORACLE中%TYPE和%ROWTYPE的使用
    A complete example using RAISE_APPLICATION_ERROR : raise_application_error
  • 原文地址:https://www.cnblogs.com/real-l/p/9927097.html
Copyright © 2020-2023  润新知