P1390 公约数的和

题意:

给定n,求
∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) \sum_{i=1}^{n}\sum_{j=i+1}^{n}gcd(i,j) i=1nj=i+1ngcd(i,j)
其中gcd(i,j)表示i和j的最大公约数。

Solution:

法一:

∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) = ∑ d = 1 n d ∑ i = 1 n ∑ j = i + 1 n [ g c d ( i , j ) = d ] = ∑ d = 1 n d ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = d ] − ∑ i = 1 n ∑ j = i i [ g c d ( i , j ) = d ] 2 = ∑ d = 1 n d ∑ i = 1 n ∑ j = 1 n [ g c d ( i d , j d ) = 1 ] − ∑ i = 1 n ∑ j = i i [ g c d ( i d , j d ) = 1 ] 2 = ∑ d = 1 n d ∑ i = 1 n d ∑ j = 1 n d [ g c d ( i , j ) = 1 ] − ∑ i = 1 n d ∑ j = i i [ g c d ( i , j ) = 1 ] 2 = ∑ d = 1 n d ∑ i = 1 n d ∑ j = 1 n d ∑ k ∣ g c d ( i , j ) μ ( k ) − ∑ i = 1 n d ∑ j = i i ∑ k ∣ g c d ( i , j ) μ ( k ) 2 = ∑ d = 1 n d ∑ k = 1 n d μ ( k ) ⌊ n k d ⌋ 2 − ⌊ n k d ⌋ 2 \sum_{i=1}^{n}\sum_{j=i+1}^{n}gcd(i,j) \\ =\sum_{d=1}^{n}d\sum_{i=1}^{n}\sum_{j=i+1}^{n}[gcd(i,j)=d] \\ =\sum_{d=1}^{n}d\frac{\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(i,j)=d]-\sum_{i=1}^{n}\sum_{j=i}^{i}[gcd(i,j)=d]}{2} \\ =\sum_{d=1}^{n}d\frac{\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(\frac{i}{d},\frac{j}{d})=1]-\sum_{i=1}^{n}\sum_{j=i}^{i}[gcd(\frac{i}{d},\frac{j}{d})=1]}{2} \\ =\sum_{d=1}^{n}d\frac{\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}[gcd(i,j)=1]-\sum_{i=1}^{\frac{n}{d}}\sum_{j=i}^{i}[gcd(i,j)=1]}{2} \\ =\sum_{d=1}^{n}d\frac{\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}\sum_{k|gcd(i,j)}\mu(k)-\sum_{i=1}^{\frac{n}{d}}\sum_{j=i}^{i}\sum_{k|gcd(i,j)}\mu(k)}{2} \\ =\sum_{d=1}^{n}d\sum_{k=1}^{\frac{n}{d}}\mu(k)\frac{\lfloor\frac{n}{kd}\rfloor^2-\lfloor\frac{n}{kd}\rfloor}{2} i=1nj=i+1ngcd(i,j)=d=1ndi=1nj=i+1n[gcd(i,j)=d]=d=1nd2i=1nj=1n[gcd(i,j)=d]i=1nj=ii[gcd(i,j)=d]=d=1nd2i=1nj=1n[gcd(di,dj)=1]i=1nj=ii[gcd(di,dj)=1]=d=1nd2i=1dnj=1dn[gcd(i,j)=1]i=1dnj=ii[gcd(i,j)=1]=d=1nd2i=1dnj=1dnkgcd(i,j)μ(k)i=1dnj=iikgcd(i,j)μ(k)=d=1ndk=1dnμ(k)2kdn2kdn

法二:

假设 f ( d ) = ∑ i = 1 n ∑ j = i + 1 n [ g c d ( i , j ) = d ] f(d)=\sum_{i=1}^{n}\sum_{j=i+1}^{n}[gcd(i,j)=d] f(d)=i=1nj=i+1n[gcd(i,j)=d]
那么根据 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d}f(d) F(n)=ndf(d)
F ( k ) = ∑ k ∣ d f ( d ) = ∑ k ∣ d ∑ i = 1 n ∑ j = i + 1 n [ g c d ( i , j ) = d ] = ∑ i = 1 n ∑ j = i + 1 n [ k ∣ g c d ( i , j ) ] = ∑ i = 1 n ∑ j = 1 n [ k ∣ g c d ( i , j ) ] − ∑ i = 1 n ∑ j = i i [ k ∣ g c d ( i , j ) ] = ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 F(k)=\sum_{k|d}f(d) \\ =\sum_{k|d}\sum_{i=1}^{n}\sum_{j=i+1}^{n}[gcd(i,j)=d] \\ =\sum_{i=1}^{n}\sum_{j=i+1}^{n}[k|gcd(i,j)] \\ =\sum_{i=1}^{n}\sum_{j=1}^{n}[k|gcd(i,j)]-\sum_{i=1}^{n}\sum_{j=i}^{i}[k|gcd(i,j)] \\ =\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} F(k)=kdf(d)=kdi=1nj=i+1n[gcd(i,j)=d]=i=1nj=i+1n[kgcd(i,j)]=i=1nj=1n[kgcd(i,j)]i=1nj=ii[kgcd(i,j)]=2kn2kn
之后根据 f ( d ) = ∑ d ∣ k μ ( k d ) F ( k ) f(d)=\sum_{d|k}\mu(\frac{k}{d})F(k) f(d)=dkμ(dk)F(k)
f ( d ) = ∑ d ∣ k μ ( k d ) F ( k ) = ∑ d ∣ k μ ( k d ) ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 f(d)=\sum_{d|k}\mu(\frac{k}{d})F(k) \\ =\sum_{d|k}\mu(\frac{k}{d})\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} f(d)=dkμ(dk)F(k)=dkμ(dk)2kn2kn
令k=td
∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) = ∑ d = 1 n d ∑ i = 1 n ∑ j = i + 1 n [ g c d ( i , j ) = d ] = ∑ d = 1 n d ∑ d ∣ k μ ( k d ) ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 = ∑ d = 1 n d ∑ t = 1 n d μ ( t ) ⌊ n t d ⌋ 2 − ⌊ n t d ⌋ 2 \sum_{i=1}^{n}\sum_{j=i+1}^{n}gcd(i,j) \\ =\sum_{d=1}^{n}d\sum_{i=1}^{n}\sum_{j=i+1}^{n}[gcd(i,j)=d] \\ =\sum_{d=1}^{n}d\sum_{d|k}\mu(\frac{k}{d})\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} \\ =\sum_{d=1}^{n}d\sum_{t=1}^{\frac{n}{d}}\mu(t)\frac{\lfloor\frac{n}{td}\rfloor^2-\lfloor\frac{n}{td}\rfloor}{2} i=1nj=i+1ngcd(i,j)=d=1ndi=1nj=i+1n[gcd(i,j)=d]=d=1nddkμ(dk)2kn2kn=d=1ndt=1dnμ(t)2tdn2tdn
最后套个数论分块就可以了

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int N=2e6;
int mu[N+5],prime[N+5],notPrime[N+5],cnt=0;
int sum[N];
void initMu()
{
   
    mu[1]=1;
    for(int i=2;i<=N;i++)
    {
   
        if(!notPrime[i])
        {
   
            prime[cnt++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<cnt&&1ll*i*prime[j]<=N;j++)
        {
   
            notPrime[i*prime[j]]=1;
            if(i%prime[j])mu[i*prime[j]]=-mu[i];
            else{
   mu[i*prime[j]]=0;break;}
        }
    }
    for(int i=1;i<=N;i++)sum[i]=sum[i-1]+mu[i];
}
int n;
ll res=0;
int main()
{
   
    initMu();
    scanf("%d",&n);

    for(int i=1;i<=n;i++)
    {
   
        ll ans=0;
        int x=n/i;
        for(int l=1,r;l<=x;l=r+1)
        {
   
            r=x/(x/l);
            ans=ans+1ll*(x/l)*(x/l-1)/2*(sum[r]-sum[l-1]);
        }
        //cout<<i*ans<<endl;
        res+=1ll*i*ans;
    }
    printf("%lld",res);
    return 0;
}

Another Solution

对于 ∑ d = 1 n d ∑ d ∣ k μ ( k d ) ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 \sum_{d=1}^{n}d\sum_{d|k}\mu(\frac{k}{d})\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} d=1nddkμ(dk)2kn2kn,根据 i d ∗ μ = φ id*\mu=\varphi idμ=φ
∑ d = 1 n ∑ d ∣ k i d ( d ) ∗ μ ( k d ) ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 = ∑ k = 1 n ∑ d ∣ k i d ( d ) ∗ μ ( k d ) ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 = ∑ k = 1 n φ ( k ) ⌊ n k ⌋ 2 − ⌊ n k ⌋ 2 \sum_{d=1}^{n}\sum_{d|k}id(d)*\mu(\frac{k}{d})\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} \\ =\sum_{k=1}^{n}\sum_{d|k}id(d)*\mu(\frac{k}{d})\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} \\ =\sum_{k=1}^n\varphi(k)\frac{\lfloor\frac{n}{k}\rfloor^2-\lfloor\frac{n}{k}\rfloor}{2} d=1ndkid(d)μ(dk)2kn2kn=k=1ndkid(d)μ(dk)2kn2kn=k=1nφ(k)2kn2kn

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int N=2e6;
int phi[N+5],prime[N+5],notPrime[N+5],cnt=0;
ll sum[N];
void initMu()
{
   
    phi[1]=1;
    for(int i=2;i<=N;i++)
    {
   
        if(!notPrime[i])
        {
   
            prime[cnt++]=i;
            phi[i]=i-1;
        }
        for(int j=0;j<cnt&&1ll*i*prime[j]<=N;j++)
        {
   
            notPrime[i*prime[j]]=1;
            if(i%prime[j])phi[i*prime[j]]=phi[i]*(prime[j]-1);
            else{
   phi[i*prime[j]]=phi[i]*prime[j];break;}
        }
    }
    for(int i=1;i<=N;i++)sum[i]=sum[i-1]+phi[i];
}
int n;
ll res=0;
int main()
{
   
    initMu();
    scanf("%d",&n);
    for(int l=1,r;l<=n;l=r+1)
    {
   
        r=n/(n/l);
        res+=1ll*(n/l)*(n/l-1)/2*(sum[r]-sum[l-1]);
    }
    printf("%lld",res);
    return 0;
}