洛谷 P2257

题目链接:P2257 YY的GCD

题目大意

\(\sum\limits_{i = 1}^{n}\sum\limits_{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) = \sum\limits_{x | d}\mu(\frac{d}{x})F(d) = \sum\limits_{x | d}\mu(\frac{d}{x})\frac{n}{d} * \frac{m}{d}\)

因为题目要求 \(gcd(x, y)\) 为质数, 那么,我们枚举会得到:

\(ans = \sum\limits_{p}^{min(n, m)}\sum\limits_{d}^{min(n, m)}\mu(d)\frac{n}{pd} * \frac{m}{pd}\)

我们这么做肯定 T

那我们继续做

我们设 \(T = pd\), 那么继续得到 \(ans = \sum\limits_{T = 1}^{min(n, m)}\frac{n}{T} * \frac{m}{T} \sum\limits_{p|T}\mu(\frac{T}{p})\)

我们预处理处所有的 \(\sum\limits_{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("");
	}
}
posted @ 2020-09-08 14:40  Aliemo  阅读(189)  评论(0)    收藏  举报