[HAOI2018] 染色

  • 面对形如\(f_j \cdot g_{j-i}\)的“差卷积”,可以通过倒置数组的方法凑出卷积的形式
#include <bits/stdc++.h>
#define int long long
using namespace std;
const signed mod=1004535809;
int w[100005],f[100005],g[100005];
int power(int n,int p)
{
	if(p==0)
	{
		return 1;
	}
	long long tmp=power(n,p/2);
	if(p%2==1)
	{
		return tmp*tmp%mod*n%mod;
	}
	return tmp*tmp%mod;
}
long long jc[10000005],jcinv[10000005];
void pre()
{
	jc[0]=1;
	for(int i=1;i<=10000000;i++)
	{
		jc[i]=jc[i-1]*i%mod;
	}
	jcinv[10000000]=power(jc[10000000],mod-2);
	for(int i=10000000-1;i>=0;i--)
	{
		jcinv[i]=jcinv[i+1]*(i+1)%mod;
	}
}
long long c(int n,int m)
{
	if(m>n)
	{
		return 0;
	}
	return jc[n]*jcinv[m]%mod*jcinv[n-m]%mod;
}
typedef vector<int> poly;
int rev[5000005],p[5000005][2];
void NTT(poly &f,int opt)
{
	int n=f.size();
	for(int i=1;i<n;i++)
	{
		if(i<rev[i])
		{
			swap(f[i],f[rev[i]]);
		}
	}
	for(int m=2;m<=n;m*=2)
	{
		int k=m/2;
		for(int i=0;i<n;i+=m)
		{
			long long cur=1,step;
			if(opt==1)
			{
				step=p[m][0];
			}
			else
			{
				step=p[m][1];
			}
			for(int j=0;j<k;j++)
			{
				long long tmp=cur*f[i+j+k]%mod;
				f[i+j+k]=(f[i+j]-tmp)%mod;
				f[i+j]=(f[i+j]+tmp)%mod;
				cur=cur*step%mod;
			}
		}
	}
}
poly operator*(poly a,poly b)
{
	poly c(a.size()+b.size()-1);
	int p=0;
	while((1<<p)<c.size())
	{
		p++;
	}
	for(int i=1;i<(1<<p);i++)
	{
		rev[i]=(rev[i>>1]>>1);
		if(i&1)
		{
			rev[i]+=(1<<(p-1));
		}
	}
	c.resize(1<<p);
	a.resize(c.size());
	b.resize(c.size());
	NTT(a,1),NTT(b,1);
	for(int i=0;i<c.size();i++)
	{
		c[i]=a[i]*b[i]%mod;
	}
	NTT(c,-1);
	p=power(c.size(),mod-2);
	for(int i=0;i<c.size();i++)
	{
		c[i]=c[i]*p%mod;
	}
	return c;
}
void ntt_pre()
{
	for(int i=1;i<=20;i++)
	{
		p[1<<i][0]=power(3,(mod-1)/(1<<i));
		p[1<<i][1]=power(3,(mod-1)-(mod-1)/(1<<i));
	}
}
void fac(int x)
{
	int p[15]={0},c[15]={0},tot=0;
	int i=2;
	while(i*i<=x)
	{
		if(x%i==0)
		{
			tot++;
			p[tot]=i;
			while(x%i==0)
			{
				c[tot]++;
				x/=i;
			}
		}
		i++;
	}
	if(x>1)
	{
		tot++;
		p[tot]=x;
		c[tot]=1;
	}
	for(int i=1;i<=tot;i++)
	{
		cout<<p[i]<<" "<<c[i]<<endl;
	}
}
ostream& operator <<(ostream& os,vector<int> x)
{
	for(int i:x)
	{
		os<<(i+mod)%mod;
		os<<' ';
	}
	return os;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	pre();
	ntt_pre();
	int n,m,s;
	cin>>n>>m>>s;
	for(int i=0;i<=m;i++)
	{
		cin>>w[i];
	}
	for(int i=0;i<=m&&i*s<=n;i++)
	{
		g[i]=c(m,i)*c(n,i*s)%mod*power(m-i,n-i*s)%mod*jc[i*s]%mod*power(jcinv[s],i)%mod*jc[i]%mod;
	}
	reverse(g,g+m+1);
	poly F,G(m+1),H(m+1);
	for(int i=0;i<=m;i++)
	{
		G[i]=g[i];
		H[i]=jcinv[i];
		if(i%2)
		{
			H[i]=-H[i];
		}
	}
	F=G*H;
	F.resize(m+1);
	reverse(F.begin(),F.end());
	int ans=0;
	for(int i=0;i<=m&&i*s<=n;i++)
	{
		F[i]=F[i]*jcinv[i]%mod;
		ans=(ans+F[i]*w[i]%mod)%mod;
	}
	cout<<(ans+mod)%mod<<endl;
	return 0;
}
posted @ 2025-05-03 11:13  D06  阅读(8)  评论(0)    收藏  举报
//雪花飘落效果