uoj#450. 【集训队作业2018】复读机(单位根反演)

题面

传送门

题解

我的生成函数和单位根反演的芝士都一塌糊涂啊……

\(d=1\),答案就是\(k^n\)(因为这里\(k\)个复读机互不相同,就是说有标号)

\(d=2\),我们考虑复读机的生成函数

\[\left(\sum_{i=0}^\infty [2|i]{x^i\over i!}\right)^k[x^n]=\left(e^x+e^{-x}\over 2\right)^k[x^n] \]

后面那个可以二项式定理展开

顺便说一下,对于形如\(e^{ax}\)项的第\(n\)项系数就是把\(e\)展开之后的第\(n\)项,即\({a^nx^n\over n!}\),我们把\(a^n\)加入答案就行了

\(d=3\),用单位根反演来化式子

\[\begin{aligned} ans &=\left(\sum_{i=0}^\infty [3|i]{x^i\over i!}\right)^k[x^n]\\ &=\left({1\over 3}\sum_{i=0}^\infty{x^i\over i!}\sum_{j=0}^{2}\omega_3^{ij}\right)^k[x^n]\\ &=\left({1\over 3}\sum_{i=0}^\infty{x^i+(x\omega_3^1)^i+(x\omega_3^2)^i\over i!}\right)^k[x^n]\\ &=\left({1\over 3}(e^x+e^{x\omega_3^1}+e^{x\omega_3^2})\right)^k[x^n]\\ \end{aligned} \]

因为\(3|P-1\),所以单位根就是\(\omega=g^{P-1\over 3}\)\(P\)的原根为\(g=7\)

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=5e5+5,P=19491001;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R ll y){
	x=(x%P+P)%P;
	R int res=1;
	for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
	return res;
}
int fac[N],ifac[N],w[5],n,k,d,res;
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
namespace solve2{
	void MAIN(){
		res=0;
		fp(i,0,k)res=add(res,mul(C(k,i),ksm(2*i-k,n)));
		res=mul(res,ksm(2,1ll*k*(P-2)%(P-1)));
		printf("%d\n",res);
	}
}
namespace solve3{
	void MAIN(){
		res=0;
		w[0]=1,w[1]=ksm(7,(P-1)/3),w[2]=mul(w[1],w[1]);
		fp(i,0,k)fp(j,0,k-i){
			int x=(1ll*i*w[0]%P+1ll*j*w[1]%P+1ll*(k-i-j)*w[2]%P)%P;
			x=ksm(x,n);
			res=add(res,1ll*C(k,i)*C(k-i,j)%P*x%P);
		}
		res=mul(res,ksm(3,1ll*k*(P-2)%(P-1)));
		printf("%d\n",res);
	}
}
int main(){
//	freopen("testdata.in","r",stdin);
	scanf("%d%d%d",&n,&k,&d);
	if(d==1)return printf("%d\n",ksm(k,n)),0;
	else{
		fac[0]=ifac[0]=1;fp(i,1,k)fac[i]=mul(fac[i-1],i);
		ifac[k]=ksm(fac[k],P-2);fd(i,k-1,1)ifac[i]=mul(ifac[i+1],i+1);
		d==2?solve2::MAIN():solve3::MAIN();
	}
	return 0;
}
posted @ 2019-03-05 10:02  bztMinamoto  阅读(308)  评论(0编辑  收藏  举报
Live2D