AcWing 220. 最大公约数
题意
给一个整数 n ( 1 ≤ n ≤ 1 0 7 ) n(1\le n \le 10^7) n(1≤n≤107) ,问 1 ≤ x , y ≤ n 1\le x,y\le n 1≤x,y≤n 且 g c d ( x , y ) gcd(x,y) gcd(x,y) 是素数的数有多少对。
解法
a n s = ∑ p ∑ x = 1 n ∑ y = 1 n [ g c d ( x , y ) = = p ] = ∑ p ∑ x = 1 n ∑ y = 1 n [ g c d ( x / p , y / p ) = = 1 ] = ∑ p ∑ x = 1 n / p ∑ y = 1 n / p [ g c d ( x , y ) = = 1 ] = ∑ p ( ∑ x = 1 n / p 2 ( ∑ y = 1 x [ g c d ( x , y ) = = 1 ] ) − 1 ) = ∑ p ( ∑ x = 1 n / p 2 φ ( x ) − 1 ) \begin{aligned} ans&=\sum_{p}\sum_{x=1}^{n}\sum_{y=1}^{n}[gcd(x,y)==p]\\ &=\sum_{p}\sum_{x=1}^{n}\sum_{y=1}^{n}[gcd(x/p,y/p)==1]\\ &=\sum_{p}\sum_{x=1}^{n/p}\sum_{y=1}^{n/p}[gcd(x,y)==1]\\ &=\sum_{p}(\sum_{x=1}^{n/p}2(\sum_{y=1}^{x}[gcd(x,y)==1])-1)\\ &=\sum_{p}(\sum_{x=1}^{n/p}2\varphi (x)-1) \end{aligned} ans=p∑x=1∑ny=1∑n[gcd(x,y)==p]=p∑x=1∑ny=1∑n[gcd(x/p,y/p)==1]=p∑x=1∑n/py=1∑n/p[gcd(x,y)==1]=p∑(x=1∑n/p2(y=1∑x[gcd(x,y)==1])−1)=p∑(x=1∑n/p2φ(x)−1)
筛出欧拉函数和 n n n 以内的质数,处理出前缀和,然后暴力加即可。
代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
#pragma endregion
const int maxn = 1e7 + 5;
int cnt = 0, prime[maxn];
bool mp[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]) {
prime[++cnt] = i;
for (int j = i; j <= n; j += i) {
if (!phi[j]) phi[j] = j;
phi[j] = phi[j] / i * (i - 1);
}
}
}
}
int phi[maxn];
ll pre[maxn];
int main() {
int n;
scanf("%d", &n);
phi_table(n, phi);
rep(i, 1, n / 2) pre[i] = pre[i - 1] + 2 * phi[i];
ll ans = 0;
rep(i, 1, cnt) {
int p = prime[i];
if (p > n) break;
ans += pre[n / p] - 1;
}
printf("%lld\n", ans);
}