UOJ450 【集训队作业2018】复读机【生成函数】

题目链接:UOJ EI神仙加强版

既然这题模数是今天日期减去\(7\times 10^5\),那就要赶紧把这题做了。

首先肯定是考虑指数型生成函数,列出来之后使用单位根反演一波。

\[\begin{aligned}Ans&=(\sum_{d|i}\frac{x^i}{i!})^k \\&=(\frac{\sum_{j=0}^{d-1}\sum_{i=0}^n\frac{(\omega_d^jx)^i}{i!}}{d})^k \\&=(\frac{\sum_{i=0}^{d-1}e^{\omega_d^ix}}{d})^k \\&=\frac{1}{d^k}(\sum_{i=0}^{d-1}e^{\omega_d^ix})^k\end{aligned} \]

\(d=1\)

\[Ans=e^{kx} \]

\(d=2\)

\[\begin{aligned}Ans&=\frac{1}{2^k}(e^x+e^{-x})^k \\&=\frac{1}{2^k}\sum_{i=0}^k\binom{k}{i}e^{(2i-k)x}\end{aligned} \]

\(d=3\)

\[\begin{aligned}Ans&=\frac{1}{3^k}(e^x+e^{\omega x}+e^{\bar\omega x})^k \\&=\frac{1}{3^k}\sum_{i=0}^k\sum_{j=0}^{k-i}\binom{k}{i,j}e^{(i+j\omega+(k-i-j)\bar\omega)x}\end{aligned} \]

时间复杂度\(O(k^{d-1}\log n)\)

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = 500003, mod = 19491001, w = 18827933, w2 = (LL) w * w % mod;
int n, k, d, fac[N], inv[N], ans;
inline void upd(int &a, int b){a += b; if(a >= mod) a -= mod;}
inline int kasumi(int a, int b){
	int res = 1;
	while(b){
		if(b & 1) res = (LL) res * a % mod;
		a = (LL) a * a % mod; b >>= 1;
	}
	return res;
}
int main(){
	scanf("%d%d%d", &n, &k, &d); n %= mod - 1;
	if(d == 1){printf("%d", kasumi(k, n)); return 0;}
	fac[0] = 1;
	for(Rint i = 1;i <= k;i ++) fac[i] = (LL) fac[i - 1] * i % mod;
	inv[k] = kasumi(fac[k], mod - 2);
	for(Rint i = k;i;i --) inv[i - 1] = (LL) inv[i] * i % mod;
	if(d == 2){
		for(Rint i = 0;i <= k;i ++)
			upd(ans, (LL) inv[i] * inv[k - i] % mod * kasumi((2 * i - k + mod) % mod, n) % mod);
		printf("%d", (LL) ans * kasumi(2, mod - 1 - k) % mod * fac[k] % mod);
	} else if(d == 3){
		for(Rint i = 0;i <= k;i ++)
			for(Rint j = 0;i + j <= k;j ++)
				upd(ans, (LL) inv[i] % mod * inv[j] % mod * inv[k - i - j] % mod *
					kasumi((i + (LL) j * w % mod + (LL) (k - i - j) * w2 % mod) % mod, n) % mod);
		printf("%d", (LL) ans * kasumi(3, mod - 1 - k) % mod * fac[k] % mod);
	}
}

EI对于这题还有一个加强版,但是我不会做,先咕了。

posted @ 2019-10-01 15:18  mizu164  阅读(254)  评论(0编辑  收藏  举报