51Nod - 1040 最大公约数之和 51Nod - 1188 最大公约数之和 V2

1040:

给出一个n,求1-n这n个数,同n的最大公约数的和。比如:n = 6

1,2,3,4,5,6 同6的最大公约数分别为1,2,3,2,1,6,加在一起 = 15

n <= 1e9

ll get_ephi(ll n) {
    ll m = int(sqrt(n + 0.5));
    ll ans = n;
    for (int i = 2; i <= m; i++) {
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
}

int main() {
    ll n;
    scanf("%lld", &n);
    if (n == 1) puts("1");
    else {
        ll res = 0;
        for (ll i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                if (i * i == n) res += get_ephi(n / i) * i;
                else res += get_ephi(n / i) * i + get_ephi(i) * n / i;
            }
        }
        printf("%lld", res);
    }
}
View Code

1188:

给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和。

1 <= T <= 50000

2 <= N <= 5000000

扫描二维码关注公众号,回复: 11440487 查看本文章
ll f[maxn];
int phi[maxn];

void phi_table(int n, int* phi) {
    for (int i = 2; i <= n; i++) phi[i] = 0;
    phi[1] = 1;
    for (int i = 2; i <= n; i++) if (!phi[i])
        for (int j = i; j <= n; j += i) {
            if (!phi[j]) phi[j] = j;
            phi[j] = phi[j] / i * (i - 1);
        }
}

void init() {
    for (int i = 1; i < maxn; i++) {
        for (int j = 2; j < maxn; j++) {
            if (i * j < maxn) f[i * j] += phi[j] * i;
            else break;
        }
    }
    for (int i = 1; i < maxn; i++) f[i] += f[i - 1];
}




int main() {
    phi_table(maxn - 3, phi);
    init();
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        printf("%lld\n", f[n]);
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/hznumqf/p/13378880.html