题解 AT3593 【Three Gluttons】
xtx1092515503 · · 题解
首先先将
考虑倒序思考。设三个人最后一个分别吃了
显然,在 C 的排列中,
现在,我们让时间回溯一格。在吃倒数第二个寿司时,限制仍是唯一的,即 C 吃的寿司在本回合中是他最喜欢的。不需要考虑 AB 这回合吃的寿司与下回合的
继续回溯的话,会发现倒数第
现在考虑当 ABC 喜好序列固定时如何判断其会不会冲突。我们考虑令
-
-
对于每个
t ,a_{i_t} 仅在\{a_1\sim a_{i_t}\}\cup\{b_1\sim b_{j_t}\}\cup\{c_1\sim c_{k_t}\} 序列中出现一次。b_{j_t},c_{k_t} 同理须满足此条件。(因为不然要么他们会有矛盾,要么就会更早被抢先吃掉)
现在考虑不知道 C 的喜好序列。则此时
其有,当且仅当:
- 无相同元素。
-
-
于是我们可以用上述条件来验证一个寿司序列是否合法。
考虑当前填到了
二者无交,则其余
于是我们设
DP的时候要注意判定限制的第二条。
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,a[410],b[410],f[410][410][410],g[410][410],res;
bool occ[410],oa[410][410],ob[410][410];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
for(int i=1;i<=n;i++){
occ[a[i]]=true;
g[i][0]=i;
for(int j=1;j<=n;j++)g[i][j]=g[i][j-1]+!occ[b[j]];
}
for(int i=1;i<=n;i++)for(int j=1;j<=i;j++)oa[i][a[j]]=true,ob[i][b[j]]=true;
// for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)printf("%d ",g[i][j]);puts("");}
n/=3;
for(int i=0;i<=3*n;i++)for(int j=0;j<=3*n;j++)f[0][i][j]=1;
for(int t=1;t<=n;t++)for(int i=t;i<=3*n;i++)for(int j=t;j<=3*n;j++){
if(!ob[j][a[i]]&&!oa[i][b[j]])f[t][i][j]=1ll*f[t-1][i-1][j-1]*(3*t-g[i][j])%mod;
f[t][i][j]=(0ll+f[t][i][j]+f[t][i-1][j]+f[t][i][j-1]+mod-f[t][i-1][j-1])%mod;
}
res=f[n][3*n][3*n];
for(int i=1;i<=n;i++)res=1ll*res*(3*i-2)*(3*i-1)%mod;
printf("%d\n",res);
return 0;
}