$P2398 GCD SUM$

Posted liuz8848

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了$P2398 GCD SUM$相关的知识,希望对你有一定的参考价值。

(Description)

(sumlimits_{i=1}^nsumlimits_{j=1}^n gcd(i,j))

(Solution)

这种(gcd)计数的题一般思想是枚举(gcd)

对于这道题,有一下几种做法,循序渐进

暴力:(O(n^2logn))

就是暴力枚举所有数求(gcd),期望得分不清楚,大概(20pts)

可以优化(gcd)函数,记忆化一下。

画个矩阵发现可以只求下三角,即只求(sumlimits_{i=1}^nsumlimits_{j=1}^{j<i}gcd(i,j)),将答案(*2)后再单独用等差数列求和公式处理对角线上的情况((i==j)),一顿操作猛如虎,但因为会(MLE)仍然无法通过(70pts)

离正解只差一步的暴力:(O(nsqrt n))

枚举所有数(i),设组成数对的另一个数为(j),仍是只考虑(i<j)的情况。设(gcd(i,j)=k),则(gcd(frac{i}{k} ,frac{j}{k})=1),符合这样的数(frac{j}{k})的个数就应该是(phi(frac{i}{k})),所以(O(sqrt n))枚举(i)的所有因数为(gcd)(ans+=gcdcdot phi(frac{i}{gcd}))。总复杂度(O(nsqrt n))

(70pts)肯定是稳过的,至此离正解只差一步。

正解(O(nln n))

上面枚举因子(O(sqrt n))显然是可以优化的,可以先枚举(gcd),再枚举另一个因子得出(i=gcd*x),和上面方法是等效的,调和级数(O(ln n))总复杂度(O(n ln n))

(Code)

int n,prime[maxn],pcnt,is_not_prime[maxn];
int phi[maxn];
ll ans;
void Get_Phi(int x)
{
    is_not_prime[1]=1;
    for(re int i=2;i<=x;++i)
    {
        if(!is_not_prime[i]) prime[++pcnt]=i,phi[i]=i-1;
        for(re int j=1;j<=pcnt;++j)
        {
            if(i*prime[j]>x) break;
            is_not_prime[i*prime[j]]=1;
            if(!(i%prime[j]))
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
}
int vis[maxn];
int main()
{
    n=read();
    Get_Phi(n);
    for(re int i=1;i<=n;++i)//枚举gcd
        for(re int j=2;j*i<=n;++j)//枚举数对中较大的数/gcd的结果,从2枚举是为了不考虑对角线 
        {
            ans+=(ll)phi[j]*i;
        }
    ans*=2;//上三角下三角 
    ans+=(ll)(1+n)*n/2;//统计对角线 
    printf("%lld
",ans);
    return 0;
}

以上是关于$P2398 GCD SUM$的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2398 GCD SUM

Copy自某谷题解UVA11417 GCD

luogu P2568 GCD

[BZOJ2820]YY的GCD

[题解]luogu P2257 YY的GCD

luogu2257 YY的GCD--莫比乌斯反演