JZOJ 5988 珂学计树题 (Burnside引理)

什么神题a…没学过Burnside引理a学了也做不来系列…考场没怎么看这题,上最后十分钟打了样例就溜了…然后这题爆0了.
Here

CODE

#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1000005;
const int mod = 998244353;
int phi[MAXN], p[MAXN], cnt;
bool vis[MAXN];

int fac[MAXN<<1], inv[MAXN<<1];
inline void Pre(int N) {
	fac[0] = fac[1] = inv[0] = inv[1] = phi[1] = 1;
	for(int i = 2; i <= N; ++i) {
		if(!vis[i]) p[++cnt] = i, phi[i] = i-1;
		for(int j = 1; j <= cnt && i*p[j] <= N; ++j) {
			vis[i*p[j]] = 1;
			if(i % p[j] == 0) {
				phi[i*p[j]] = phi[i] * p[j];
				break;
			}
			phi[i*p[j]] = phi[i] * (p[j]-1);
		}
	}
	for(int i = 2; i <= N<<1; ++i) fac[i] = 1ll * fac[i-1] * i % mod, inv[i] = 1ll * (mod - mod/i) * inv[mod%i] % mod;
	for(int i = 2; i <= N<<1; ++i) inv[i] = 1ll * inv[i-1] * inv[i] % mod;
}
inline int C(int N, int M) {
	if(M > N) return 0;
	return 1ll * fac[N] * inv[M] % mod * inv[N-M] % mod;
}
inline int INV(int a) {
	int b = mod-2, res = 1;
	while(b) {
		if(b&1) res = 1ll * res * a % mod;
		a = 1ll * a * a % mod; b >>= 1;
	}
	return res;
}
int main () {
	freopen("tree.in", "r", stdin);
	freopen("tree.out", "w", stdout);
	int n;
	scanf("%d", &n); Pre(n);
	int ans = 0;
	for(int d = 1; d*d <= n; ++d) if(n % d == 0) {
		ans = (ans + 1ll * phi[n/d] * C(d<<1, d) % mod) % mod;
		if(d*d < n) ans = (ans + 1ll * phi[d] * C(n/d<<1, n/d) % mod) % mod;
	}
	printf("%d
", int(1ll*ans*INV(n<<1)%mod));
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039344.html