限制颜色数的同色不相邻染色计数
NaCly_Fish · · 题解
题目链接
要将
这个题我确实没想到什么简洁快速的做法,本题解仅作为抛砖引玉。
在末尾补充了优化做法,就是比原做法更简单还快的。
设
现在尝试提取其
可以发现一个关于
一次变换的复杂度可以做到
最后的问题就是,这个做法如何继续优化呢?感觉有点困难,还请指点一下。
参考代码:
// this is just a trivial and brutal solution.
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define N 262147
#define ll long long
#define p 1000000007
using namespace std;
inline int power(int a,int t){
int res = 1;
while(t){
if(t&1) res = (ll)res*a%p;
a = (ll)a*a%p;
t >>= 1;
}
return res;
}
int fac[N],ifac[N];
void init(int n){
fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
for(int i=2;i<=n;++i) fac[i] = (ll)fac[i-1]*i%p;
ifac[n] = power(fac[n],p-2);
for(int i=n-1;i;--i) ifac[i] = (ll)ifac[i+1]*(i+1)%p;
}
inline int binom(int n,int m){
if(n<m) return 0;
return (ll)fac[n]*ifac[m]%p*ifac[n-m]%p;
}
void transform(const int *f,int n,int m,int *r){
static int g[N];
memset(g,0,(n+m+1)<<2);
for(int k=0;k<=n;++k)
for(int i=1;i<=min(m,k);++i){
int tmp = (ll)f[k]*binom(k,i)%p*binom(m-1,m-i)%p,t;
for(int j=0;j<=(i<<1);++j){
t = k+m-(i<<1)+j;
g[t] = (g[t]+(ll)tmp*binom(i<<1,j))%p;
}
}
memcpy(r,g,(n+m+1)<<2);
}
int f[N];
int T,k,m,deg;
int main(){
init(23333);
scanf("%d",&T);
while(T--){
scanf("%d",&k);
f[1] = deg = 1;
for(int i=1;i<k;++i){
scanf("%d",&m);
transform(f,deg,m,f);
deg += m;
}
scanf("%d",&m);
printf("%d\n",f[m]);
memset(f,0,(deg+1)<<2);
}
return 0;
}
实际上这题用容斥就很简单。枚举对于每种颜色,产生的相邻对数
这个式子中
括号里面那一大块是个多重排列,因为强制
最后那个
这个式子就可以用生成函数改写一下了,设
则答案为
设