UVA11426 GCD

题意:输入n,问所有gcd(i, j)的和,1<=i<j<=n,2<=n<=4000000

题解:可以发现是递推得到ans[n] = ans[n-1]+f[n],f[n]就代表了n和小于n的数的gcd的和,求f[n]可以由因子推得,枚举gcdb就是n的因子,gcd(n, a) = b所以gcd(n/b, a/b) = 1就是求与n/b互质的数有几个,也就是欧拉函数,这里用因子来推,每个因子对他的倍数都有贡献,预处理一下

#include <bits/stdc++.h>
#define ll long long
#define maxn 4000100
using namespace std;
ll ans[maxn], f[maxn], phi[maxn];
void init(ll num){
    for(int i=2;i<=num;i++) phi[i] = 0;
    phi[1] = 1;
    for(int i=2;i<=num;i++){
        if(!phi[i])
        for(int j=i;j<=num;j+=i){
            if(!phi[j]) phi[j] = j;
            phi[j] = phi[j]/i*(i-1);
        }
        for(ll j=1;j*i<=num;j++)
            f[i*j] += phi[i]*j;
    }
}
int main(){
    ll n;
    init(4000000);
    for(ll i=2;i<=4000000;i++)
        ans[i] = ans[i-1]+f[i];
    while(~scanf("%lld", &n)&&n)
        printf("%lld
", ans[n]);
    return 0;
}
原文地址:https://www.cnblogs.com/Noevon/p/7410008.html