competitive programming problems
最初的想法是令 \(dp[i][2,1,0]\) 分别表示第 \(i\) 位是最大、次大、其他的合法排列数。转移考虑最大和次大从 \(i + D[i]\) 位置转移过来,之间的元素需要保证合法,注意到最大值和次大值转移完全相同,所以可以把两种情况整合成一种。
这样做整体时间复杂度为 \(O(n^2)\),似乎没什么好的优化方法。
点击查看代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define int long long
const int mod=998244353;
using namespace std;
int n,dp[100010][2];
int a[100010];
signed main() {
cin>>n;
for (int i=1;i<n;++i) {
cin>>a[i];
}
if (a[n-1]==1) dp[n-1][1]=1;
for (int i=n-2;i>=1;--i) {
int base=1;
for (int j=i+a[i]-1;j>=i+1;--j) {
if (a[j]==a[j+1]&&a[j]==i+a[i]-j) base*=n-j;
else if (a[j]==a[j+1]) base*=n-j-1;
else if (a[j]==i+a[i]-j) base*=1;
else {
base=0;
break;
}
}
dp[i][1]=dp[i+a[i]][1]*base,dp[i][1]%=mod;
if (a[i]==a[i+1]) dp[i][0]=(dp[i+1][0]+dp[i+1][1]*2)*(n-i-1),dp[i][0]%=mod;
}
cout<<(dp[1][0]+dp[1][1]*2)%mod<<endl;
return 0;
}

浙公网安备 33010602011771号