Petit_Souris
2024-11-19 20:32:59
设
于是可以直接进行 dp 了。设
如果这个数已经出现,直接放到对应位置上。如果没有出现,放在前面就是枚举一个
注意特判无解的情况。
#include<bits/stdc++.h>
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define pii pair<ll,ll>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define per(i,a,b) for(ll i=(a);i>=(b);--i)
using namespace std;
bool Mbe;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void write(ll x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
const ll N=5009,Mod=998244353;
ll n,a[N],pos[N],dp[N][N],suf[N],sq[N],sum[N],b[N],c[N];
bool Med;
int main(){
cerr<<fabs(&Med-&Mbe)/1048576.0<<"MB\n";
n=read();
rep(i,1,n)a[i]=read();
if(n<=10){
rep(i,1,n)b[i]=i;
ll ans=0;
do{
rep(i,1,n)c[i]=b[i];
rep(i,1,n-1){
if(c[i]>c[i+1])swap(c[i],c[i+1]);
}
ll fl=1;
rep(i,1,n){
if(~a[i]&&c[i]!=a[i]){
fl=0;
break;
}
}
if(fl)ans++;
}while(next_permutation(b+1,b+n+1));
write(ans%Mod);
return 0;
}
rep(i,1,n){
if(~a[i])pos[a[i]]=i;
}
if(pos[n]&&pos[n]!=n)return puts("0"),0;
if(~a[n]&&a[n]!=n)return puts("0"),0;
a[n]=n,pos[n]=n;
per(i,n,1){
suf[i]=suf[i+1];
if(!~a[i])suf[i]++;
}
dp[n][n]=1;
per(i,n,1){
sq[i]=sq[i+1];
if(!pos[i])sq[i]++;
}
per(i,n,1){
per(j,n,1)sum[j]=(sum[j]+sum[j+1])%Mod;
rep(j,1,n){
if(!~a[j])dp[i][j]=(dp[i][j]+sum[j])%Mod;
}
if(i==1)break;
memset(sum,0,sizeof(sum));
rep(j,1,n){
if(!dp[i][j])continue;
ll cnt=suf[j]-sq[i];
if(cnt<0)continue;
if(pos[i-1]){
if(pos[i-1]==j)continue;
if(pos[i-1]>j)dp[i-1][j]=(dp[i-1][j]+dp[i][j])%Mod;
else dp[i-1][pos[i-1]]=(dp[i-1][pos[i-1]]+dp[i][j]*2)%Mod;
}
else {
dp[i-1][j]=(dp[i-1][j]+dp[i][j]*cnt)%Mod;
sum[j-1]=(sum[j-1]+dp[i][j]*2)%Mod;
}
}
}
write(dp[1][1]%Mod),putchar('\n');
cerr<<"\n"<<clock()*1.0/CLOCKS_PER_SEC*1000<<"ms\n";
return 0;
}