题目链接:P2257 YY的GCD
题目大意
(sumlimits_{i = 1}^{n}sumlimits_{j = 1}^{m}[gcd(i, j) == d]) , 其中 (d) 为质数
solution
我们设 (f(n)) 为满足 (gcd(x, y) == d) 的 ((x, y)) 的对数
(F(d)) 为满足 (d | gcd(x, y)) 的对数
那么 (F(x) = frac{n}{x} * frac{m}{x}), 反演后得到:
(f(x) = sumlimits_{x | d}mu(frac{d}{x})F(d) = sumlimits_{x | d}mu(frac{d}{x})frac{n}{d} * frac{m}{d})
因为题目要求 (gcd(x, y)) 为质数, 那么,我们枚举会得到:
(ans = sumlimits_{p}^{min(n, m)}sumlimits_{d}^{min(n, m)}mu(d)frac{n}{pd} * frac{m}{pd})
我们这么做肯定 T 飞 了
那我们继续做
我们设 (T = pd), 那么继续得到 (ans = sumlimits_{T = 1}^{min(n, m)}frac{n}{T} * frac{m}{T} sumlimits_{p|T}mu(frac{T}{p}))
我们预处理处所有的 (sumlimits_{p | T}mu(frac{T}{p})), 这道题就解决了
Code:
/**
* Author: Alieme
* Data: 2020.9.8
* Problem: P2257
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define rr register
#define inf 1e9
#define MAXN 10000001
using namespace std;
inline void read(int &T) {
T = 0;
int f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) T = T * 10 + (ch ^ 48), ch = getchar();
if (f) T = -T;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
int tot, n, m, T, ans;
int u[MAXN], prime[MAXN], g[MAXN], sum[MAXN];
bool vis[MAXN];
inline void init() {
u[1] = 1;
for (rr int i = 2; i < MAXN; i++) {
if (!vis[i]) prime[++tot] = i, u[i] = -1, g[i] = 1;
sum[i] = sum[i - 1] + g[i];
for (rr int j = 1; j <= tot && i * prime[j] < MAXN; j++) {
vis[i * prime[j]] = 1;
if (i % prime[j]) {
u[i * prime[j]] = -u[i];
g[i * prime[j]] = u[i] - g[i];
}
else {
u[i * prime[j]] = 0;
g[i * prime[j]] = u[i];
break;
}
}
}
}
signed main() {
init();
read(T);
while (T--) {
read(n), read(m);
ans = 0;
if (n < m) swap(n, m);
for (rr int l = 1, r; l <= m; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += (n / l) * (m / l) * (sum[r] - sum[l - 1]);
}
print(ans);
puts("");
}
}