【BZOJ4407】于神之怒加强版

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	5000005
#define P	1000000007
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 k, tot, prime[MAXN];
int f[MAXN], g[MAXN], miu[MAXN];
long long sum[MAXN];
long long power(long long x, long long y) {
	if (y == 0) return 1;
	long long tmp = power(x, y / 2);
	if (y % 2 == 0) return tmp * tmp % P;
	else return tmp * tmp % P * x % P;
}
void init(int n) {
	miu[1] = 1; sum[1] = 1;
	for (int i = 2; i <= n; i++) {
		if (f[i] == 0) {
			f[i] = g[i] = prime[++tot] = i;
			long long tmp = power(i, k), now = tmp;
			miu[i] = -1; sum[i] = tmp - 1;
			for (int j = i; n / j >= i; j *= i) {
				sum[j * i] = now * tmp - now;
				now = now * tmp % P;
			}
		} else sum[i] = sum[g[i]] * sum[i / g[i]] % P;
		for (int j = 1; j <= tot && prime[j] <= f[i]; j++) {
			int tmp = prime[j] * i;
			if (tmp > n) 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 <= n; i++)
		sum[i] = (sum[i] + sum[i - 1]) % P;
}
int main() {
	int T;
	read(T), read(k);
	init(MAXN - 1);
	while (T--) {
		int n, m, nxt = 0, mxt = 0, tmp = 0;
		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 = (ans + (sum[tmp] - sum[i - 1]) * (n / i) % P * (m / i)) % P;
		}
		printf("%lld\n", (ans % P + P) % P);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80513931
今日推荐