Uva11426 数论gcd( x, n ) x小于n 的和

题目大意:

输入n(2<=n<=4000000)输出gcd(i, j) (1<=i

gcd(1, 2) + 
gcd(1, 3) + gcd(2, 3) + 
gcd(1, 4) + gcd(2, 4)+ gcd(3, 4) + 
+......+
…… + gcd(n-1, n)
设:f(n) = gcd(1, n)+gcd(2, n)+gcd(3, n)++ gcd(n-1, n): S(n)= f(2)+f(3)++ f(n)

那么:S(n)=s(n-1)+f(n)
我们把f(n)求出来,再递推一下。

对于:gcd(x, n)= i, 那么i一定是n的因数。
假设:g(n, i) 表示满足gcd(x, n)=i 并且x<n的个数。
那么:f(n) = i*gcd(n, i) i是n的约数

gcd(x, n)= i 等价gcd(x/i, n/i)=1。
所有gcd(x, n)= i等于gcd(x/i, n/i)=1的个数。g(n, i)=phi[n/i]
Phi[] 欧拉函数。

所以:f(n) = i* Phi[n/i] i是n的约数
我们对于每个i枚举倍数n。
#include
#define LL long long
using namespace std;

const int N=4000000;
LL euler[N+5];//存储欧拉函数值
LL s[N+5], f[N+5];
void Init()
{
    euler[1]=1;
    for(int i=2;i<N;i++)
    euler[i]=i;
    for(int i=2;i<N;i++)  {
        if(euler[i]==i)
        {
            for(int j=i;j<N;j+=i)
            euler[j]=euler[j]/i*(i-1);
        }
    }
}

int main()
{
    Init();
    memset(f, 0, sizeof(f));
    for(int i=1; i<=N; i++){
        for(int n=i*2; n<=N; n+=i){//n!=i, 因为gcd(x, n)=i xi
            f[n]+=i*euler[n/i];
        }
    }

    s[2]=f[2];
    for(int n=3; n<=N; n++){
        s[n]=s[n-1]+f[n];
    }

    int n;
    while(scanf("%d", &n), n){
        printf("%lld\n", s[n]);
    }

    return 0;
}

你可能感兴趣的:(数论)