于神之怒加强版 简要题解

这道题的式子可以硬推, 也可以按 (f(gcd(i,j)) = (1*g) (gcd(i,j))) 的套路来快速得出答案(其实总行数没少几行qwq), 不细说。

最后要算的就是:

[sum_{T=1}^{min(n,m)} lfloor frac{n}T floor lfloor frac{m}T floor sum_{d|T} d^k mu(frac{T}d) ]

如果去掉(mu(frac{T}d)), 那么我将绝杀, 但是去不得

所以怎么预处理(sum_{d|T} d^k mu(frac{T}d))

我的方法是把它拆成 (id_k * mu), 就可以 (O(T log log T)) 搞, 可以过。((id_k) 是完全积性函数,可以线性筛出来, 复杂度大约有 (O(n + prime\_cnt log k))

神仙们的线性筛以后会补qwq

Luogu数据AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e6 + 15;
const int mod = 1000000007;
#define li long long
li ksm(li a, li b, li p) {
	li res = 1ll;
	for(;b;b>>=1, a=(a*a)%p)
		if(b&1) res = (res*a)%p;
	return res%p;
}

int t; li k;
int pr_cnt, prime[maxn], v[maxn];
li idk[maxn], g[maxn];
void euler(int n) {
	idk[1] = 1ll;
	for(int i=2; i<=n; ++i) {
		if(!v[i]) {
			v[prime[++pr_cnt] = i] = i;
			idk[i] = ksm(i, k, mod);
		}
		for(int j=1; j<=pr_cnt; ++j) {
			if(prime[j] > n/i || prime[j] > v[i]) break;
			v[prime[j] * i] = prime[j];
			idk[prime[j] * i] = idk[i] * idk[prime[j]] % mod;
		}
	}
	for(int i=1; i<=n; ++i) g[i] = idk[i];
	for(int i=1; i<=pr_cnt; ++i)
		for(int j=n/prime[i]; j>0; --j) {
			g[prime[i] * j] -= g[j];
			g[prime[i] * j] = (g[prime[i] * j]%mod+mod)%mod;
		}
	for(int i=2; i<=n; ++i) {
		g[i] += g[i-1];
		g[i] = (g[i]%mod+mod)%mod;
	}
}

int main()
{
	cin >> t >> k;
	euler(5000000);
	while(t--) {
		int n, m; scanf("%d%d", &n,&m);
		int len = min(n,m);
		li ans = 0ll;
		for(int i=1,j; i<=len; i=j+1) {
			j = min(n/(n/i), m/(m/i));
			j = min(j, len);
			ans += (g[j]-g[i-1]) * (n/i) % mod * (m/i) % mod;
			ans = (ans%mod+mod)%mod;
		}
		cout << ans << '
';
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tztqwq/p/12765057.html