Acwing 220 最大公约数

题意:

给定整数对$N$, 求$1 \leq x, y \leq N$ 且 $gcd(x, y)$为质数的数对$(x, y)$有多少对

思路:

枚举$1 \leq p \leq N$所有质数$p$, $gcd(x, y) = p$即$gcd(\frac{x}{p}, \frac{y}{p}) = 1$,则统计$1 \leq x, y \leq \frac{N}{p}$内有多少个数对$(x, y)$满足$gcd(x, y) = 1$即可

如何统计:对每个数x记录与其互质的数的数量(欧拉筛)并预处理欧拉函数的前缀和,枚举质数$p$,$ans +=(sum[n/p] * 2 - 1)$(其中$sum[n/p]$为$1 \leq x, y \leq \frac{N}{p}$的欧拉函数前缀和,乘$2$是因为所得的所有$(x, y)$为一个解,$(y, x)$也是一个解。减$1$是因为当$x = 1$时,$y = 1$,则$(x, y) (y, x)$都为$(1, 1)$,会重复)

Code:

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#include <map>
#include <set>
// #include <array>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
// #include <unordered_map>

using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

#define Time (double)clock() / CLOCKS_PER_SEC

#define sd(a) scanf("%d", &a)
#define sdd(a, b) scanf("%d%d", &a, &b)
#define slld(a) scanf("%lld", &a)
#define slldd(a, b) scanf("%lld%lld", &a, &b)

const int N = 1e7 + 20;
const int M = 1e6 + 20;
const int mod = 1e9 + 7;

int n, m;
ll sum[N];
bool st[N];
int primes[N], cnt, phi[N];

void get(int n){
    phi[1] = 1, sum[1] = 1;
    for(int i = 2; i <= n; i ++){
        if(!st[i]){
            primes[cnt ++] = i;
            phi[i] = i - 1;
        }
        sum[i] = sum[i - 1] + phi[i];
        for(int j = 0; primes[j] <= n / i; j ++){
            st[i * primes[j]] = true;
            if(i % primes[j] == 0){
                phi[i * primes[j]] = primes[j] * phi[i];
                break;
            }
            phi[i * primes[j]] = (primes[j] - 1) * phi[i];
        }
    }
}

void solve()
{
    sd(n);
    ll ans = 0;
    for(int i = 0; primes[i] <= n; i ++){
        ans +=  (sum[n / primes[i]] * 2 - 1);
    }
    cout << ans << endl;
    
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("/home/jungu/code/in.txt", "r", stdin);
    // freopen("/home/jungu/code/out.txt", "w", stdout);
#endif
    // ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T = 1;
    get(N - 20);
    // sd(T);
    while (T--)
    {
        solve();
    }

    return 0;
}

 

posted @ 2020-08-02 12:08  君顾  阅读(147)  评论(0)    收藏  举报