链接
题解
要想让同色不相邻,我可以在 d p dp dp的过程中加入一维, d p i j dp_{ij} dpij表示使用了前 i i i种颜色,整个序列被切成了 j j j段的方案数。切段的目的是让同色的分开,切开的断面将来是要与异色的段。
用 g i , j , k g_{i,j,k} gi,j,k表示 i i i段颜色 A A A的和 j j j段颜色 B B B的合成 k k k段,且同色的段不能相邻的方案数,注意如果开一个 n × c m a x × n n\times c_max \times n n×cmax×n的数组会 m l e mle mle,经过分析之后可以发现 i > ⌊ n + 1 2 ⌋ i>\lfloor \frac{n+1}{2} \rfloor i>⌊2n+1⌋或 k > ⌊ n + 1 2 ⌋ k>\lfloor \frac{n+1}{2} \rfloor k>⌊2n+1⌋的状态对答案没有贡献,所以我可以只 d p dp dp到 n / 2 + ϵ n/2+\epsilon n/2+ϵ(其中 ϵ \epsilon ϵ是自己随便规定的一个数,我程序里是 5 5 5)
那么
d
p
dp
dp方程如下:
d
p
i
j
=
∑
k
=
0
n
/
2
+
ϵ
d
p
i
−
1
,
k
×
g
k
,
c
i
dp_{ij} = \sum_{k=0}^{n/2+\epsilon} dp_{i-1,k} \times g_{k,c_i}
dpij=k=0∑n/2+ϵdpi−1,k×gk,ci
代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 901
#define maxk 31
#define maxc 31
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
#define mod 1'000'000'007
int f[maxn/2+10][maxc][maxn/2+10][2], c[maxk], dp[maxk][maxn/2+10];
int main()
{
ll i, j, k, n, K, T=read();
while(T--)
{
K=read();
n=0;
rep(i,1,K)c[i]=read(),n+=c[i];
rep(i,0,n/2+5)rep(j,0,30)rep(k,1,n/2+5)f[i][j][k][0]=f[i][j][k][1]=0;
f[1][0][1][0]=f[0][1][1][1]=1;
rep(i,0,n/2+5)rep(j,0,30)rep(k,1,n/2+5)
{
auto &F=f[i][j][k];
if(i)F[0]+=(f[i-1][j][k-1][0]+f[i-1][j][k-1][1])%mod+f[i-1][j][k][1];
if(j)F[1]+=(f[i][j-1][k-1][0]+f[i][j-1][k-1][1])%mod+f[i][j-1][k][0];
F[0]%=mod, F[1]%=mod;
}
rep(i,1,K)rep(j,1,n/2+5)dp[i][j]=0;
dp[0][0]=1;
rep(i,1,K)rep(j,1,n/2+5)rep(k,0,n/2+5)
{
ll t=(f[k][c[i]][j][0]+f[k][c[i]][j][1])%mod;
(dp[i][j]+=(ll)dp[i-1][k]*t%mod)%=mod;
}
printf("%d\n",dp[K][1]);
}
return 0;
}