UVA11426 GCD - Extreme (II) 究極GCD 歐拉函數

  • 題目鏈接

  • 題意
    輸入正整數n,求gcd(1,2)+gcd(1,3)+gcd(2,3)+...+gcd(n1,n), 即求所有滿足1i<jn 的數對(i,j) 所對應的gcd(i,j) 之和。

  • 分析

    f(n)=gcd(1,n)+gcd(2,n)+gcd(3,n)+...+gcd(n1,n), 則答案爲S(n)=f(2)+f(3)+...+f(n),S(n)=S(n1)+f(n)
    g(n,i) 表示滿足gcd(x,n)=ix<n 的正整數x 的個數,則f(n)=sum{ig(n,i)|in}
    若依次計算f(n) ,速度較慢,但可以逆向思維,對每個i 枚舉它的倍數n (並更新f(n) 的值),時間複雜度與素數篩法一樣。

  • 代碼

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=4e6+2;
ll s[maxn],f[maxn];
int n;
int p[maxn+10]={0};
void init()
{
    int i,j;
    for(i=1; i<=maxn; i++)  p[i]=i;
    for(i=2; i<=maxn; i+=2) p[i]/=2;
    for(i=3; i<=maxn; i+=2)
        if(p[i]==i){
            for(j=i; j<=maxn; j+=i)
                p[j]=p[j]/i*(i-1);
        }
}

int main()
{
    init();
    memset(f,0,sizeof(f));
    for(int i=1;i<=maxn;++i)
        for(int n=i+i;n<=maxn;n+=i)
            f[n]+=i*p[n/i];
    s[2]=f[2];
    for(int i=3;i<=maxn;++i)
        s[i]=s[i-1]+f[i];
    while(scanf("%d",&n),n)
        printf("%lld\n",s[n]);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章