[FJWC2020] lg

首先对\(\operatorname{lcm}\)按各个质因子的贡献处理。

设当前质因子为\(p^q\),需要计算出\(\operatorname{lcm}\)\(p^q\)\(\gcd\)和。

这里计算\(\operatorname{lcm}\)恰好含有\(p^q\)的不方便,可以设\(\operatorname{lcm}\)\(p\)的指数小于\(q\)的进行求和,然后转化成\(x_i\)不能是\(p^q\)的倍数。

然后设\(\gcd\)\(p\)质因子含有\(p^a\),则剩余部分\(\gcd\)不能出现\(p\)的倍数,也不能有数达到\(p^{q-a}\)

按照套路,可以枚举所有数都是是\(T\)的倍数的组数\(S\)\(\gcd\)和就是\(\sum S \cdot \varphi(T)\),因为\(\varphi * \mathbf{I} = \mathbf{id}\),每个\(\gcd\)都会在它的约数处被统计一次,也可以用 Mobius 反演证。

最后就是要设法统计出不是\(p\)的倍数的数的个数。显然\(T \nmid p\),把不合法的减掉就好。还要满足不能每个数都是\(p\)的倍数,因此要减掉约掉\(T\)\(\gcd\)仍含\(p\)的倍数的,于是式子:(设\(N = \lfloor \dfrac{m}{p^a} \rfloor\)),以下都是整除:

\[\sum_{T=1}^N\Big(({N \over T} - {N \over Tp^{q-a}})^n - ({N \over Tp} - {N \over Tp^{q-a}})^n\Big) \varphi(T) \]

最后统计答案即可。

这里全部使用整除分块实现,复杂度\(\mathcal O(n \log \log n + N\sqrt N)\),其中\(\sqrt N\)上不带任何\(\log\)可以用等比数列求和分析出。

Code

#include <cstdio>
#include <algorithm>
#include <cassert>
using namespace std;
#define File(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
typedef long long ll;

const int M = 200005, mod = 998244353, mod1 = 998244352;
int pown[M];
template<int mod>
inline int power(int x, int y){
	int res = 1;
	for(; y; y>>=1, x = (1LL * x * x) % mod) if(y & 1) res = (1LL * res * x) % mod;
	return res;
}

bool np[M];
int pr[M], phi[M], pc = 0;
int phiMp[M];
void primeList(int n){
	phi[1] = 1;
	for(int i=2; i<=n; i++){
		if(!np[i]) pr[++pc] = i, phi[i] = i - 1;
		for(int j=1; j<=pc && i * pr[j] <= n; j++){
			np[i * pr[j]] = true;
			if(i % pr[j] == 0){
				phi[i * pr[j]] = phi[i] * pr[j];
				break;
			}
			phi[i * pr[j]] = phi[i] * (pr[j] - 1);
		}
	}
	for(int i=2; i<=n; i++) phi[i] = (phi[i] + phi[i-1]) % mod1;
}

int main(){
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i=1; i<=m; i++) pown[i] = power<mod1>(i, n);
	primeList(m);
	int res = 1;
	int compGCD = 0;
	for(int l=1, r; l<=m; l=r+1){
		r = m / (m / l);
		compGCD = (compGCD + 1LL * pown[m / l] * (mod1 + phi[r] - phi[l - 1]) % mod1) % mod1;
	}
	for(int i=1; i<=pc; i++){
		int p = pr[i];
		for(int j=1; j<=m/p; j++)
			phiMp[j] = (0LL + phiMp[j-1] + (phi[j * p] - phi[j * p - 1] + mod1) % mod1) % mod1;
		ll pq = p;
		int nows, lasts = 0;
		int sum = 0;
		int q;
		for(q=1; pq<=m; ++q, pq *= p){ // LCM : p^(q-1)	
			ll pa = 1;
			nows = 0;
			for(int a=0; a<q; a++, pa *= p){ // GCD : p^a
				int N = m / pa;
				int last = pq / pa;
				int now = 0;
				for(int l=1, r; l<=N; l=r+1){ // Last part GCD
					r = N / (N / l);
					int val1 = (N / l) - (N / l / last), val2 = (N / l / p) - (N / l / last);
					now = (now + 1LL * pown[val1] * ((mod1 + phi[r] - phi[l-1]) % mod1)) % mod1;
					now = (now + mod1 - 1LL * pown[val2] * ((mod1 + phi[r] - phi[l-1]) % mod1)) % mod1;
					now = (now + mod1 - 1LL * pown[val1] * ((mod1 + phiMp[r / p] - phiMp[(l - 1) / p]) % mod1) % mod1) % mod1;
					now = (now + 1LL * pown[val2] * ((mod1 + phiMp[r / p] - phiMp[(l - 1) / p]) % mod1) % mod1) % mod1;
				}
				nows = (nows + now * pa) % mod1;
			}
			sum = (sum + 1LL * (nows - lasts + mod1) % mod1 * (q - 1)) % mod1;
			lasts = nows;
		}
		sum = (sum + 1LL * (mod1 + compGCD - lasts) % mod1 * (q-1) % mod1) % mod1;
		res = (1LL * res * power<mod>(p, sum)) % mod;
	}
	printf("%d\n", res);
	return 0;
}
posted @ 2020-02-23 16:10  RiverHamster  阅读(161)  评论(0编辑  收藏  举报
\