UVA11426 GCD - Extreme (II) (欧拉函数/莫比乌斯反演)

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\times k,b\times k)=k\to gcd(a,b)=1\),我们枚举这两个数中大的那个,另一个数就有\(phi[i](1<=i <=n/k)\)个,所以\(f[n]=\sum_{i=1}^{n}\phi(i)\)

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

Code

#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;
    }
}

猜你喜欢

转载自www.cnblogs.com/real-l/p/9927097.html