2021.3.16爆零赛

2021.3.16爆零赛

题面:链接: https://pan.baidu.com/s/1Kqo-eupvcdk25pm_Dmy0YQ 提取码: eykg

吐了,期望:80+20+5,实际:50+20+5
大常数竟是我自己
考试时打第二题时证了个假的时间复杂度,然后兴致勃勃地打起了第一题。现在非常后悔,非常后悔😃
第一题不是很难,先推了下\(dp\)式,弄下生成函数,然后就调了3个小时😄,弄了个\(80pt\)的部分分,最后被卡常掉了\(30pt\)
结果第三题没怎么看,现在想来\(30pt\)也不是很难拿
以后还是要多康下部分分,小蒟蒻还是不要一来就去盯着正解\((个\_个)\)

T1.染色问题

比较简单,定义状态\(f_{i,j}\)为从后往前涂,涂完第\(j\)种颜色,剩余\(i\)个位置无色的方案数。

易得如下转移方程

\[f_{x,1}=x+1(x<n)\\f_{x,y}=f_{x,y-1}+(x+1)\sum_{i=1}^\infty f_{x+i,y-1}\\\\ \]

我们设\(g_{x,y}=\sum_{i=y}^\infty f_{i,x}\),可得如下递推式

\[g_{i,j}=g_{i,j+1}+g_{i-1,j}-g_{i-1,j+1}+(j+1)g_{i-1,j+1}\\ =g_{i,j+1}+g_{i-1,j}+jg_{i-1,j+1}\\ \]

\(g_y\)表示\(g_{x,y}\)关于\(x\)的生成函数

不难得到下式

\[g_j+1={(1+jx)(g_{j+1}+1)\over 1-x}\\ g_0+1=(g_{n-1}+1)\prod_{i=0}^{n-2}{1+ix\over 1-x}\\ g_1+1=(g_{n-1}+1)\prod_{i=1}^{n-2}{1+ix\over 1-x} \]

我们可以分治\(NTT\)求出\(\prod (1+ix)\),再多项式快速幂求出\(({1\over 1-x})^k\)

时间复杂度为:

\[T(n)=2T(\frac{n}{2})+n\log_2n \]

能得\(80pt\)可这关一个被卡常的人什么事?

#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define Type template<typename T>
# define read read1<ll>()
Type T read1(){
	T t=0;
	char k;
	bool vis=0;
	do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
	while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
	return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define mod 998244353
int n,m;
namespace A{
	int f[5005][5005],g[5005][5005];
	int MAIN(){
		for(int i=n;i--;)g[1][i]=g[1][i+1]+(f[1][i]=i+1);
		for(int i=2;i<=m;++i)
			for(int j=n;j--;)
				g[i][j]=(g[i][j+1]+(f[i][j]=(f[i-1][j]+1ll*(j+1)*g[i-1][j+1])%mod))%mod;
		cout<<f[m][0];
		return 0;
	}	
}
namespace B{
	const int g=3,invg=332748118,inv2=499122177;
	int r[2097153],gv[33005][2],nv[33005][2],invt[2097153];
	void init(const int N=32768){
		gv[0][0]=nv[0][0]=gv[0][1]=nv[0][1]=1;
		for(int i=1;i<=N;++i)nv[i][0]=1ll*nv[i-1][0]*g%mod;
		for(int i=1;i<=N;++i)nv[i][1]=1ll*nv[i-1][1]*nv[N][0]%mod;
		for(int i=1;i<=N;++i)gv[i][0]=1ll*gv[i-1][0]*invg%mod;
		for(int i=1;i<=N;++i)gv[i][1]=1ll*gv[i-1][1]*gv[N][0]%mod;
		invt[1]=1;
		for(int i=2;i<=2097152;++i)
			invt[i]=1ll*(mod-mod/i)*invt[mod%i]%mod;
	}
	int qkpow(int n,int m){
		if(!m)return 1;
		ll t=qkpow(n,m>>1);t=t*t%mod;
		if(m&1)t=t*n%mod;
		return t;
	}int Qkpow(int n,int m){
		if(n==g)return 1ll*nv[m&32767][0]*nv[m>>15][1]%mod;
		return 1ll*gv[m&32767][0]*gv[m>>15][1]%mod;
	}int Log2(double x){
        if(x==1)return 0;
		return ((*(unsigned ll*)&x>>52)&1023)+1;
	}
	void NTT(int *a,int s,bool ty){
		int L=Log2(s);r[0]=0;
		for(int i=0;i<s;++i){
			r[i]=(r[i>>1]>>1)|((i&1)<<L-1);
			if(r[i]>i)swap(a[r[i]],a[i]);
		}
		for(int i=1;i<s;i<<=1){
			int T=Qkpow(ty?invg:g,(mod-1)/(i<<1));
			ll v=1;
			for(int w=i<<1,j=0;j<s;j+=w,v=1)
				for(int k=0;k<i;++k,v=1ll*v*T%mod){
					int x=a[j+k],y=1ll*a[i+j+k]*v%mod;
					a[j+k]=(x+y)%mod;a[i+j+k]=(x-y+mod)%mod;
				}
		}
		if(ty){ll invs=invt[s];
			for(int i=0;i<s;++i)
				a[i]=invs*a[i]%mod;
		}
	}
	int *w,*u,s=1,*v,*G,*x,*y;
	void solve(int l,int r,int w,int L){
		memset(x+w,0,L<<2);
		if(l>r){
			x[w]=1;
			return;
		}
		if(l==r){
			x[w]=1;
			x[w+1]=l;
			return;
		}int mid=l+r>>1;
		solve(l,mid,w,L>>1);
		solve(mid+1,r,w+(L>>1),L>>1);
		memset(y+w+(L>>1),0,L<<1);
		memcpy(y+w,x+w+(L>>1),L<<1);
		memset(x+w+(L>>1),0,L<<1);
		NTT(x+w,L,0);NTT(y+w,L,0);
		for(int i=0;i<L;++i)x[i+w]=1ll*x[i+w]*y[i+w]%mod;
		NTT(x+w,L,1);
	}
	int* pow(int *x,int n){
		int *y=new int[s]();y[0]=1;
		for(;n;n>>=1){
			NTT(x,s,0);
			if(n&1){
				NTT(y,s,0);
				for(int i=0;i<s;++i)y[i]=1ll*y[i]*x[i]%mod;
				NTT(y,s,1);
				for(int i=m+1;i<s;++i)y[i]=0;
			}
			for(int i=0;i<s;++i)x[i]=1ll*x[i]*x[i]%mod;
			NTT(x,s,1);
			for(int i=m+1;i<s;++i)x[i]=0;
		}
		return y;
	}
	int MAIN(){init();
		int M=max(n,m);
		if(n==1)return puts("1"),0;
		while(s<=M+M)s<<=1;u=new int[s]();
		x=new int[s]();y=new int[s]();
		solve(1,n-2,0,s);w=x;
		for(int i=0;i<=m;++i)u[i]=1;
		v=pow(u,n-1);G=new int[s]();
		for(int i=1;i<=m;++i)G[i]=n;G[0]=1;
		NTT(G,s,0);NTT(v,s,0);
		for(int i=0;i<s;++i)G[i]=1ll*G[i]*v[i]%mod;
		NTT(G,s,1);
		NTT(G,s,0);NTT(w,s,0);
		for(int i=0;i<s;++i)G[i]=1ll*G[i]*w[i]%mod;
		NTT(G,s,1);
		int vx=G[m],vv=0;
		solve(1,n-2,0,s);w=x;
		memset(u,0,sizeof(u));
		for(int i=0;i<=m;++i)u[i]=1;
		v=pow(u,n-2);G=new int[s]();
		for(int i=1;i<=m;++i)G[i]=n;G[0]=1;
		NTT(G,s,0);NTT(v,s,0);
		for(int i=0;i<s;++i)G[i]=1ll*G[i]*v[i]%mod;
		NTT(G,s,1);
		NTT(G,s,0);NTT(w,s,0);
		for(int i=0;i<s;++i)G[i]=1ll*G[i]*w[i]%mod;
		NTT(G,s,1);vv=G[m];
		cout<<(vx-vv+mod)%mod;
		return 0;
	}
}
int main(){
	fre("color");
	n=read,m=read;
	if(n<=5000&&m<=5000)A::MAIN();
	else B::MAIN();
	return 0;
}

我们可以发现,\(\prod_{i=l}^{l+n-1}(1+ix)\)\(\prod_{i=l+n}^{l+2n-1}(1+ix)\)有着些内在关联

\(F(x)=x^n\prod_{i=l}^{r}(\frac{1}{x}+i)=x^n\sum_{i=0}^na_ix^{-i}\)

则右式为\(F_0(x)=x^n\sum_{i=0}^na_i(x^{-1}+n)^i\)

二项式展开:

\[\begin{align} F_0(x)&=x^n\sum_{i=0}^na_i\sum_{j=0}^i{i\choose j}x^{-j}n^{i-j}\\ &=x^n\sum_{i=0}^ni!a_i\sum_{j=0}^i\frac{x^{-j}}{j!}.{n^{i-j}\over(i-j)!} \end{align} \]

差不多就是这样,咕咕咕

posted @ 2021-03-16 21:07  ファイナル  阅读(147)  评论(1编辑  收藏  举报