[ARC118E]Avoid Permutations 题解
Umbrella_Leaf · · 题解
称不能经过的坐标
首先我们考虑,对于一个固定的排列
对每个关键点,我们有两种选择:无视,或者经过但是答案乘上
那么有了不固定排列之后还是可以这样 DP:设
这样直接转移就能够以
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=998244353;
int n,m;
int a[205],b[205];
ll dp[205][205][205][2][2];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)b[i]=-1;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]>0)b[a[i]]=i;
else m++;
}
dp[0][0][0][1][1]=1;
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+1;j++)
for(int k=0;k<=m;k++)
for(int p=0;p<2;p++)
for(int q=0;q<2;q++)if(dp[i][j][k][p][q]){
if(i<=n){
dp[i+1][j][k][a[i+1]>=0][q]=(dp[i+1][j][k][a[i+1]>=0][q]+dp[i][j][k][p][q])%mod;
if(a[i+1]==j&&j)dp[i+1][j][k][1][1]=(dp[i+1][j][k][1][1]-dp[i][j][k][p][q]+mod)%mod;
if(a[i+1]<0&&!q)dp[i+1][j][k+1][1][1]=(dp[i+1][j][k+1][1][1]-dp[i][j][k][p][q]+mod)%mod;
}
if(j<=n){
dp[i][j+1][k][p][b[j+1]>=0]=(dp[i][j+1][k][p][b[j+1]>=0]+dp[i][j][k][p][q])%mod;
if(b[j+1]==i&&i)dp[i][j+1][k][1][1]=(dp[i][j+1][k][1][1]-dp[i][j][k][p][q]+mod)%mod;
if(b[j+1]<0&&!p)dp[i][j+1][k+1][1][1]=(dp[i][j+1][k+1][1][1]-dp[i][j][k][p][q]+mod)%mod;
}
}
ll ans=0,now=1;
for(int i=m;i>=0;i--)ans=(ans+dp[n+1][n+1][i][1][1]*now%mod)%mod,now=now*(m-i+1)%mod;
printf("%lld\n",ans);
return 0;
}