competitive programming problems

ABC457F

  最初的想法是令 \(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;
}
posted @ 2026-05-31 18:47  Jyulia  阅读(23)  评论(0)    收藏  举报