码迷,mamicode.com
首页 > 其他好文 > 详细

$P2398\ GCD\ SUM$

时间:2019-11-13 16:37:14      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:记忆   操作   ++   优化   情况   pts   solution   ret   mit   

\(Description\)

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

\(Solution\)

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

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

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

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

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

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

离正解只差一步的暴力:\(O(n\sqrt 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+=gcd\cdot \phi(\frac{i}{gcd})\)。总复杂度\(O(n\sqrt 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\n",ans);
    return 0;
}

$P2398\ GCD\ SUM$

标签:记忆   操作   ++   优化   情况   pts   solution   ret   mit   

原文地址:https://www.cnblogs.com/Liuz8848/p/11849629.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!