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

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

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

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

[egin{aligned}Ans&=(sum_{d|i}frac{x^i}{i!})^k \&=(frac{sum_{j=0}^{d-1}sum_{i=0}^nfrac{(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})^kend{aligned} ]

(d=1)

[Ans=e^{kx} ]

(d=2)

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

(d=3)

[egin{aligned}Ans&=frac{1}{3^k}(e^x+e^{omega x}+e^{aromega x})^k \&=frac{1}{3^k}sum_{i=0}^ksum_{j=0}^{k-i}inom{k}{i,j}e^{(i+jomega+(k-i-j)aromega)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对于这题还有一个加强版,但是我不会做,先咕了。

原文地址:https://www.cnblogs.com/AThousandMoons/p/11615434.html