Luogu P2568 GCD problem solution

topic

Category talk

For a number satisfying the requirements of (x, y), there are two cases:

A: x, y, there is a prime number p, p is a multiple of another number, this time gcd (x, y) p apparently, to meet the requirements

B: x = p · k1, y = p · k2, p is a prime number, and k1, k2 coprime, gcd (x, y) is also a prime number p

Calculation program

First with a linear prime sieve and recursive functions Euler the preprocessing 1 - Euler function prime number n and the number of each

In the case of
A: Each enumerator prime, attention (x, y) and (y, x) is different, so is multiplied by 2, but x, y can only be considered a kind of the same, so by subtracting 2 1

B: Enumeration 1 - n for each number i, x = p · k1, y = p · k2 (p is a prime number), where k1 is the number of i are satisfied :( p · k1 <= n and p <= the number of the prime number p i,) * (before i and i the number of mutually prime numbers (the Euler function)), note also multiplied by 2

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 5;
int n, tot, k[N], p[N], a[N], s[N];
long long res;
void Pre_work () {
    for (int i = 2; i <= n; ++i) {
        if (!k[i]) p[++tot] = i, a[i] = i - 1;   //如果是质数,与 i 互质的数的个数为 i-1 
        for (int j = 1; j <= tot, p[j] * i <= n; ++j) {
            k[p[j] * i] = 1, a[p[j] * i] = a[i] * (p[j] - (i % p[j] != 0));  //套用欧拉函数递推式 
            if (i % p[j] == 0) break;
        }
    }
    for (int i = 2; i <= n; ++i) s[i] = s[i - 1] + (k[i] == 0);     //预处理质数个数的前缀和 
}
int main() {
    scanf ("%d", &n);
    Pre_work ();
    for (int i = 2; i <= n; ++i) res += s[n / i] * (a[i] - 1) << 1;   //情况 B  
    for (int i = 1; i <= tot and p[i] <= n; ++i) res += ((n / p[i]) << 1) - 1; //情况 A 
    printf ("%lld\n", res);
    return 0;
} 

Guess you like

Origin www.cnblogs.com/whx666/p/11923723.html