[LibreOJ 3120]【CTS2019】珍珠 【生成函数】【计数】

37 篇文章 0 订阅
35 篇文章 0 订阅

Description

在这里插入图片描述
在这里插入图片描述

Solution

有一个直观的思路是考虑每种颜色个数的奇偶性,奇数个数的颜色不能超过 n − 2 m n-2m n2m
因此若 n − 2 m ≥ D n-2m\geq D n2mD则答案一定是 D n D^n Dn

否则由于每种颜色其实没有区别,我们考虑一种颜色为奇数和为偶数的指数型生成函数
奇数是 e x − e − x 2 e^x-e^{-x}\over 2 2exex,偶数是 e x + e − x 2 e^x+e^{-x}\over 2 2ex+ex

我们枚举有多少个奇数的颜色
容易得到
A n s = n ! ∑ i = 0 n − 2 m ( D i ) ( e x − e − x 2 ) i ( e x + e − x 2 ) D − i [ x n ] Ans=n!\sum\limits_{i=0}^{n-2m}{D\choose i}\left({e^x-e^{-x}\over 2}\right)^i\left({e^x+e^{-x}\over 2}\right)^{D-i}[x^n] Ans=n!i=0n2m(iD)(2exex)i(2ex+ex)Di[xn]

我考场上写的是这个式子(和题解的本质相同,不过化起来比较麻烦)

提出一个 2 − D 2^{-D} 2D,把后面的东西二项式展开

= 2 − D n ! ∑ i = 0 n − 2 m ( D i ) ∑ p = 0 i e ( 2 p − i ) x ( i p ) ( − 1 ) i − p ∑ q = 0 D − i e ( 2 q + i − D ) x ( D − i q ) [ x n ] =2^{-D}n!\sum\limits_{i=0}^{n-2m}{D\choose i}\sum\limits_{p=0}^{i}e^{(2p-i)x}{i\choose p}(-1)^{i-p}\sum\limits_{q=0}^{D-i}e^{(2q+i-D)x}{D-i\choose q}[x^n] =2Dn!i=0n2m(iD)p=0ie(2pi)x(pi)(1)ipq=0Die(2q+iD)x(qDi)[xn]

此处我们可以枚举 T = p + q T=p+q T=p+q,并移到最外层

= 2 − D n ! ∑ T = 0 D e 2 T − D ∑ i = 0 n − 2 m ( D i ) ∑ p + q = T ( − 1 ) i − p ( i p ) ( D − i q ) [ x n ] =2^{-D}n!\sum\limits_{T=0}^{D}e^{2T-D}\sum\limits_{i=0}^{n-2m}{D\choose i}\sum\limits_{p+q=T}(-1)^{i-p}{i\choose p}{D-i\choose q}[x^n] =2Dn!T=0De2TDi=0n2m(iD)p+q=T(1)ip(pi)(qDi)[xn]
容易知道 n ! e p x [ x n ] = p n n!e^{px}[x^n]=p^n n!epx[xn]=pn
把q换成T-p
= 2 − D ∑ T = 0 D ( 2 T − D ) n ∑ i = 0 n − 2 m ∑ p = 0 T ( − 1 ) i − p ( D i ) ( i p ) ( D − i T − p ) =2^{-D}\sum\limits_{T=0}^{D}(2T-D)^n\sum\limits_{i=0}^{n-2m}\sum\limits_{p=0}^{T}(-1)^{i-p}{D\choose i}{i\choose p}{D-i\choose T-p} =2DT=0D(2TD)ni=0n2mp=0T(1)ip(iD)(pi)(TpDi)

考场上的时候我就卡在这里推不动了
实际上那三个组合数可以化开成 D ! i ! ( D − i ) ! i ! ( i − p ) ! p ! ( D − i ) ! ( T − p ) ! ( D − i − T + p ) ! {D!\over i!(D-i)!}{i!\over (i-p)!p!}{(D-i)!\over (T-p)!(D-i-T+p)!} i!(Di)!D!(ip)!p!i!(Tp)!(DiT+p)!(Di)!

分配阶乘,约分,补上一个 ( D − T ) ! T ! ( D − T ) ! T ! (D-T)!T!\over (D-T)!T! (DT)!T!(DT)!T!
可以得到
= 2 − D ∑ T = 0 D ( 2 T − D ) n ( D T ) ∑ i = 0 n − 2 m ∑ p = 0 T ( − 1 ) i − p ( T p ) ( D − T i − p ) =2^{-D}\sum\limits_{T=0}^{D}(2T-D)^n{D\choose T}\sum\limits_{i=0}^{n-2m}\sum\limits_{p=0}^{T}(-1)^{i-p}{T\choose p}{D-T\choose i-p} =2DT=0D(2TD)n(TD)i=0n2mp=0T(1)ip(pT)(ipDT)

可以发现后面是两个二项式卷积的形式
实际上就是 ( ( 1 + y ) T ( 1 − y ) D − T ) [ y i ] \left((1+y)^T(1-y)^{D-T}\right)[y^i] ((1+y)T(1y)DT)[yi]
后面的就和题解是一样的了。

题解的推法是这样的
A n s = n ! ∑ i = 0 n − 2 m ( y e x − e − x 2 + e x + e − x 2 ) D [ x n ] [ y i ] Ans=n!\sum\limits_{i=0}^{n-2m}\left(y{e^x-e^{-x}\over 2}+{e^x+e^{-x}\over 2}\right)^D[x^n][y^i] Ans=n!i=0n2m(y2exex+2ex+ex)D[xn][yi]
e x e^x ex e − x e^{-x} ex分开
A n s = 2 − D n ! ∑ i = 0 n − 2 m ( e x ( 1 + y ) + e − x ( 1 − y ) ) D [ x n ] [ y i ] Ans=2^{-D}n!\sum\limits_{i=0}^{n-2m}\left(e^x(1+y)+e^{-x}(1-y)\right)^D[x^n][y^i] Ans=2Dn!i=0n2m(ex(1+y)+ex(1y))D[xn][yi]
二项式展开
A n s = 2 − D n ! ∑ i = 0 n − 2 m ∑ T = 0 D e ( 2 T − D ) x ( 1 + y ) T ( 1 − y ) D − T ( D T ) [ x n ] [ y i ] Ans=2^{-D}n!\sum\limits_{i=0}^{n-2m}\sum\limits_{T=0}^{D}e^{(2T-D)x}(1+y)^T(1-y)^{D-T}{D\choose T}[x^n][y^i] Ans=2Dn!i=0n2mT=0De(2TD)x(1+y)T(1y)DT(TD)[xn][yi]
i i i放到后面去,就是
= 2 − D ∑ T = 0 D ( 2 T − D ) n ( D T ) ∑ i = 0 n − 2 m ( ( 1 + y ) T ( 1 − y ) D − T ) [ y i ] =2^{-D}\sum\limits_{T=0}^{D}(2T-D)^n{D\choose T}\sum\limits_{i=0}^{n-2m}\left((1+y)^T(1-y)^{D-T}\right)[y^i] =2DT=0D(2TD)n(TD)i=0n2m((1+y)T(1y)DT)[yi]

(看来是我的推法太蠢了)

记后面的东西 F ( T , D ) = ∑ i = 0 n − 2 m ( ( 1 + y ) T ( 1 − y ) D − T ) [ y i ] F(T,D)=\sum\limits_{i=0}^{n-2m}\left((1+y)^T(1-y)^{D-T}\right)[y^i] F(T,D)=i=0n2m((1+y)T(1y)DT)[yi]
接下来就是高端操作时间
把一个 ( 1 + y ) (1+y) (1+y)拆成 − ( 1 − y ) + 2 -(1-y)+2 (1y)+2,式子就可以化开成两边,具体略去
立刻可以得到 F ( T , D ) = − F ( T − 1 , D ) + 2 F ( T − 1 , D − 1 ) F(T,D)=-F(T-1,D)+2F(T-1,D-1) F(T,D)=F(T1,D)+2F(T1,D1)

然后 F ( 0 , D ) = ∑ i = 0 n − 2 m ( D i ) ( − 1 ) i F(0,D)=\sum\limits_{i=0}^{n-2m}{D\choose i}(-1)^i F(0,D)=i=0n2m(iD)(1)i
通过杨辉三角的性质,化到上一行去发现都消掉了,结果就是 ( D − 1 n − 2 m ) ( − 1 ) n − 2 m {D-1\choose n-2m}(-1)^{n-2m} (n2mD1)(1)n2m

然后就可以通过NTT加速递推过程求出 F ( T , D ) F(T,D) F(T,D)了。

实际上网上似乎有一种很简单的推法,利用容斥,变成至少i个为奇数,然后式子就好化很多,结果就是两次直接的卷积,就不需要后面的高端操作了。
时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 100005
#define M 262144
#define T 18
#define mo 998244353
#define LL long long
using namespace std;
LL l,n,m,js[M+1],ns[M+1],ny[M+1];
LL ksm(LL k,LL n)
{
	k=(k+mo)%mo;
	LL s=1;
	for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
	return s;
}
LL C(int n,int m)
{
	if(n<m||n<0||m<0) return 0;
	return js[n]*ns[m]%mo*ns[n-m]%mo;
}
int a[M+1],b[M+1];
LL F(int w)
{
	if(w==0) return 1;
	return ((n-2*m)&1)?(mo-C(w-1,n-2*m))%mo:C(w-1,n-2*m);
}

int bit[M+1];
int wi[M+1];
namespace polynomial
{
	void prp()
	{
		LL v=ksm(3,(mo-1)/M);
		wi[0]=1;
		fo(i,1,M) 
		{
			wi[i]=(LL)wi[i-1]*v%mo;
			bit[i]=(bit[i>>1]>>1)|((i&1)<<(T-1));
		}
	}
	int inc(int a,int b)
	{
		return (a+=b)>=mo?a-mo:a;
	}
	int dec(int a,int b)
	{
		return (a-=b)<0?a+mo:a;
	}
	void DFT(int *a)
	{
		fo(i,0,M-1) if(bit[i]<i) swap(a[i],a[bit[i]]);
		for(int h=1,l=(M>>1),v;h<M;h<<=1,l>>=1) 
		{
	   		for(int j=0;j<M;j+=h<<1) 
	   		{
	        	int *x=a+j,*y=x+h,*w=wi;
				for(int i=0;i<h;++i,++x,++y,w+=l)
				{
	        		v=((LL)*y * *w)%mo;
	        		*y=dec(*x,v);
	        		*x=inc(*x,v);
	        	}
	      	}
	    }
	}
	void IDFT(int *a)
	{
		DFT(a);
		fo(i,0,M-1) a[i]=a[i]*ny[M]%mo;
		reverse(a+1,a+M);
	}
}
using polynomial::prp;
using polynomial::DFT;
using polynomial::IDFT;
int main()
{
	cin>>l>>n>>m;
	if(n-2*m>=l) 
	{
		printf("%lld\n",ksm(l,n));
		return 0;
	} 
	js[0]=js[1]=ny[1]=ns[0]=ns[1]=1;
	fo(i,2,M) 
	{
		js[i]=js[i-1]*(LL)i%mo;
		ny[i]=(-ny[mo%i]*(LL)(mo/i)%mo+mo)%mo;
		ns[i]=ns[i-1]*ny[i]%mo; 
	}
	LL v=1;
	fo(i,0,l) 
	{
		a[i]=v*ns[i]%mo*F(l-i)%mo,b[i]=(LL)((i&1)?mo-1:1)*ns[i]%mo;
		v=v*(LL)2%mo; 
	}
	prp();
	DFT(a),DFT(b);
	fo(i,0,M-1) a[i]=(LL)a[i]*(LL)b[i]%mo;
	IDFT(a);
	LL ans=0;
	fo(i,0,l) ans=(ans+a[i]*js[i]%mo*ksm(2*i-l,n)%mo*C(l,i))%mo;
	printf("%lld\n",ans*ksm(ksm(2,l),mo-2)%mo);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值