【BZOJ3994】【SDOI2015】约数个数和

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	50005
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
int tot, prime[MAXN];
int f[MAXN], g[MAXN];
int miu[MAXN];
long long d[MAXN];
void init() {
	miu[1] = 1; d[1] = 1;
	for (int i = 2; i < MAXN; i++) {
		if (f[i] == 0) {
			f[i] = g[i] = prime[++tot] = i;
			miu[i] = -1; d[i] = 2;
			int now = 3;
			for (int j = i; (MAXN - 1) / j >= i; j *= i, now++)
				d[j * i] = now;
		} else d[i] = d[g[i]] * d[i / g[i]];
		for (int j = 1; j <= tot && prime[j] <= f[i]; j++) {
			int tmp = prime[j] * i;
			if (tmp >= MAXN) break;
			f[tmp] = prime[j];
			if (prime[j] == f[i]) miu[tmp] = 0, g[tmp] = g[i] * f[i];
			else miu[tmp] = -miu[i], g[tmp] = prime[j];
		}
	}
	for (int i = 2; i < MAXN; i++) {
		miu[i] += miu[i - 1];
		d[i] += d[i - 1];
	}
}
int main() {
	init();
	int T; read(T);
	while (T--) {
		int n, m, nxt = 0, mxt = 0, tmp;
		long long ans = 0;
		read(n), read(m);
		if (n > m) swap(n, m);
		for (int i = 1; i <= n; i = tmp + 1) {
			if (i > nxt) nxt = n / (n / i);
			if (i > mxt) mxt = m / (m / i);
			tmp = min(nxt, mxt);
			ans += (miu[tmp] - miu[i - 1]) * d[n / i] * d[m / i];
		}
		printf("%lld\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80515595