其他分享
首页 > 其他分享> > P2398 GCD SUM

P2398 GCD SUM

作者:互联网

P2398 GCD SUM

题目大意

\(\sum_{i=1}^n \sum_{j=1}^n \gcd(i, j)\)

分析

这个到是蛮好想的,我们推理一下。

\(\sum_{i=1}^n \sum_{j=1}^n \gcd(i, j) = \sum_{k=1}^n k*\sum_{x=1}^{\left \lfloor \frac{n}{k} \right \rfloor} \sum_{y=1}^{\left \lfloor \frac{n}{k} \right \rfloor} [gcd(i, j)]\)

接下来,我们的问题就转化为了,枚举k,判断一个二维区间\(\{(x,y)|1 \leq x \leq \left \lfloor \frac{n}{k} \right \rfloor,1 \leq y \leq \left \lfloor \frac{n}{k} \right \rfloor\}\),其中有多少个数对其gcd(x,y)=1,求出数量后*k,将所有k的答案累加起来即为最后答案。

那如何判断一个二维区间互质的点对数量呢,这就是经典问题了。

先说结论,若二维区间是\(\{(x,y)|1 \leq x \leq n,1 \leq y \leq m\}\),则答案即为\(\sum_{i=1}^{n}\phi(i)+\sum_{i=1}^{m}\phi(i)-1\)

扩展的话,即为区间的左下点不一定就是(1,1),但这个就不展开说了,因为就是类似于一个二维前缀和的东西,很简单。

这个结论也很好推理,给个提示,将矩形的左下角和右上角相连,接着分别从左边画横线,下边画竖线,就很容易理解了。

时间复杂度\(O(n)\)

Ac_code

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;

int n;
int phi[N],Primes[N],cnt;
LL s[N];
bool st[N];
void get_eulers()
{
    phi[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!st[i]) Primes[cnt++]=i,phi[i]=i-1;
        for(int j=0;Primes[j]*i<N;j++)
        {
            st[Primes[j]*i]=1;
            if(i%Primes[j]==0)
            {
                phi[Primes[j]*i]=phi[i]*Primes[j];
                break;
            }
            else phi[i*Primes[j]]=phi[i]*(Primes[j]-1);
        }
    }
    for(int i=1;i<N;i++) s[i] = s[i-1] + phi[i];
}

int main()
{
    ios;
    cin>>n;
    get_eulers();
    LL ans = 0;
    for(int i=1;i<=n;i++){
        LL t = n/i;
        ans += (2*s[t]-1)*i;
    }
    cout<<ans<<endl;
    return 0;
}

标签:lfloor,right,GCD,int,sum,rfloor,P2398,leq,SUM
来源: https://www.cnblogs.com/aitejiu/p/16661351.html