[CTS2019]珍珠

传送门

一个长度为(n)的序列,每个位置可以自由填(1-D),问有多少种情况使得序列中可以找出(m)对相同的数

假设数字(i)出现了(sum_i)次,那么需要满足

[sumlimits_{i=1}^{D}lfloorfrac{sum_i}{2} floorge m ]

[sumlimits_{i=1}^{D}frac{sum_i-sum_i\%2}{2}ge m ]

[sumlimits_{i=1}^{D}sum_i-sum_i\%2ge 2*m ]

[n-sumlimits_{i=1}^{D}sum_i\%2ge 2*m ]

[sumlimits_{i=1}^{D}sum_i\%2le n-2*m ]

设恰好有(i)个颜色数为奇数的方案数为(g_i),那么(ans=sumlimits_{i=0}^{n-2m}g_i)

(f_i)为有(i)种颜色数量是奇数,其他颜色数随便的方案数,可以得到

[f_i=sumlimits_{j=i}^{D}dbinom{j}{i}g_j ]

根据二项式反演有

[g_i=sumlimits_{j=i}^{D}(-1)^{j-i}dbinom{j}{i}f_j ]

考虑求一波(f_i)

颜色出现次数为奇数的(EGF{0,1,0,1,0,1,……})(frac{e^x-e^{-x}}{2})

其他颜色随便排列的(EGF{1,1,1,1,1,……})(e^x)

根据(EGF)得到

[f_i=dbinom{D}{i}n![x^n](frac{e^x-e^{-x}}{2})^i(e^x)^{D-i} ]

[=dbinom{D}{i}frac{n!}{2^i}[x^n](e^x-e^{-x})^i(e^x)^{D-i} ]

将中间二项式展开

[=dbinom{D}{i}frac{n!}{2^i}[x^n]sumlimits_{j=0}^{i}dbinom{i}{j}(e^x)^{j}(-e^{-x})^{i-j}(e^x)^{D-i} ]

[=dbinom{D}{i}frac{n!}{2^i}sumlimits_{j=0}^{i}dbinom{i}{j}(-1)^{i-j}[x^n]e^{(D-2(i-j))x} ]

根据(e^{ax}=sumlimitsfrac{a^n}{n!}),代入得到

[=dbinom{D}{i}frac{n!}{2^i}sumlimits_{j=0}^{i}dbinom{i}{j}(-1)^{i-j}frac{(D-2(i-j))^n}{n!} ]

我们由枚举(j)变为枚举(i-j)得到

[=dbinom{D}{i}frac{n!}{2^i}sumlimits_{j=0}^{i}dbinom{i}{j}(-1)^jfrac{(D-2j)^n}{n!} ]

展开组合数

[=frac{D!}{(D-i)!2^i}sumlimits_{j=0}^{i}frac{(-1)^j(D-2j)^n}{j!}*frac{1}{(i-j)!} ]

显然右边是个卷积,可以(O(DlogD))(f_i)

再考虑

[g_i=sumlimits_{j=i}^{D}(-1)^{j-i}dbinom{j}{i}f_j ]

将组合数拆开

[g_i=sumlimits_{j=i}^{D}(-1)^{j-i}frac{j!}{i!(j-i)!}f_j ]

[g_i=frac{1}{i!}sumlimits_{j=0}^{D-i}frac{(-1)^j}{j!}(i+j)!f_{i+j} ]

(a_i=frac{(-1)^i}{i!},b_i=i!f_i)(a^{'})(a)的翻转,得到

[c_{D+i}=sumlimits_{j=0}^{D-i}frac{(-1)^j}{j!}(i+j)!f_{i+j}=sumlimits_{j=0}^{D-i}a^{'}_{D-j}b_{i+j} ]

也是一个卷积,可以(O(DlogD))求解

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
	inline int read()
	{
		int x=0;char ch,f=1;
		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
		if(ch=='-') f=0,ch=getchar();
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
		return f?x:-x;
	}
	const int N=4e5+10,p=998244353,inv2=(p+1)>>1;
	int D,n,m,ans;
	int fac[N],inv[N];
	int f[N],g[N];
	int limit=1,len;
	int pos[N];
	inline int fast(int x,int k)
	{
		int ret=1;
		while(k)
		{
			if(k&1) ret=ret*x%p;
			x=x*x%p;
			k>>=1;
		}
		return ret;
	}
	inline void ntt(int *a,int inv)
	{
		for(int i=0;i<limit;++i)
			if(i<pos[i]) swap(a[i],a[pos[i]]);
		for(int mid=1;mid<limit;mid<<=1)
		{
			int Wn=fast(3,(p-1)/(mid<<1));
			for(int r=mid<<1,j=0;j<limit;j+=r)
			{
				int w=1;
				for(int k=0;k<mid;++k,w=w*Wn%p)
				{
					int x=a[j+k],y=w*a[j+k+mid]%p;
					a[j+k]=(x+y)%p;
					a[j+k+mid]=(x-y+p)%p;
				}
			}
		}
		if(inv) return;
		inv=fast(limit,p-2);reverse(a+1,a+limit);
		for(int i=0;i<limit;++i) a[i]=a[i]*inv%p;
	}
	inline void main()
	{
		D=read(),n=read(),m=read();
		if(D<=n-2*m) return(void)(printf("%lld
",fast(D,n)));
		if(2*m>n) return(void)puts("0");
		for(int i=fac[0]=1;i<=D;++i) fac[i]=fac[i-1]*i%p;
		inv[D]=fast(fac[D],p-2);
		for(int i=D-1;~i;--i) inv[i]=inv[i+1]*(i+1)%p;
		for(int i=0;i<=D;++i) f[i]=fast((D-2*i+p)%p,n)*(i&1?p-inv[i]:inv[i])%p;
		for(int i=0;i<=D;++i) g[i]=inv[i];
		while(limit<=2*D) limit<<=1,++len;
		for(int i=1;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
		ntt(f,1);ntt(g,1);
		for(int i=0;i<limit;++i) f[i]=f[i]*g[i]%p;
		ntt(f,0);
		for(int i=0;i<=D;++i) f[i]=f[i]*fac[D]%p*fac[i]%p*inv[D-i]%p*fast(inv2,i)%p;
		for(int i=0;i<=D;++i) g[D-i]=(i&1)?p-inv[i]:inv[i];
		for(int i=D+1;i<limit;++i) f[i]=g[i]=0;
		ntt(f,1);ntt(g,1);
		for(int i=0;i<limit;++i) f[i]=f[i]*g[i]%p;
		ntt(f,0);
		for(int i=0;i<=n-2*m;++i) ans=(ans+f[i+D]*inv[i])%p;
		printf("%lld
",ans);
	}
}
signed main()
{
	red::main();
	return 0;
}
原文地址:https://www.cnblogs.com/knife-rose/p/13044542.html