Array Without Local Maximums
Ivan unexpectedly saw a present from one of his previous birthdays. It is array of nn numbers from 1 to 200. Array is old and some numbers are hard to read. Ivan remembers that for all elements at least one of its neighbours ls not less than it, more formally:
a1≤a2,
an≤an−1 and
ai≤max(ai−1,ai+1) for all ii from 2 to n−1.
Ivan does not remember the array and asks to find the number of ways to restore it. Restored elements also should be integers from 1 to 200. Since the number of ways can be big, print it modulo 998244353.
Input
First line of input contains one integer nn (2≤n≤105) — size of the array.
Second line of input contains nn integers aiai — elements of array. Either ai=−1 or 1≤ai≤200. ai=−1 means that i-th element can't be read.
Output
Print number of ways to restore the array modulo 998244353998244353.
Input
3
1 -1 2
Output
1
Input
2
-1 -1
200
In the first example, only possible value of a2 is 2.
In the second example, a1=a2 so there are 200 different values because all restored elements should be integers between 1 and 200.
题意:
有一个长度为n的序列,满足对于所有的a[x],与它相邻的两个元素a[x-1]和a[x+1]中至少有一个大于等于它,其中a[1]和a[n]当然只有一个相邻元素(可以默认i<1 || i>n 的数组值为0 即(a[0]==0 || a[n+1]==0)),现在这个序列中的有些数字被破坏了(标记为-1),问有多少种合法恢复方案(每个数字∈[1,200])
题解:
对于一可行序列,只考虑最后三位,共有如下排列方式
此图来自别人博客
那么对于这9种情况只有 这一种情况是是不符合的排除这一种即可
与
有三种关系,<,=,>。这里的dp[i][j][k]代表第i个位置为为j且与前面的
的关系为k的方案数
那么状态转移方程为
1. dp[i][j][0]=(dp[i−1][k][0]+dp[i−1][k][1]+dp[i−1][k][2])
因为<
时,那么
可以和
满足任何条件
2. dp[i][j][1]=dp[i−1][j][0]+dp[i−1][j][1]+dp[i−1][j][2]
这里与1的不同之处就是=
。
3. dp[i][j][2]=(dp[i−1][k][2]+dp[i−1][k][1])
因为>
,所以必须要
<=
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=1e5+5;
const int mod=998244353;
int a[maxn];
ll dp[maxn][205][3];
// 0: a[i-1] < a[i] 1: a[i-1] = a[i] 2: a[i-1] < a[i]
int main()
{
int n;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
//可以理解为<1的位置a[i](即a[0])一定为0,不存在其他可能只可能小于a[1] 并且 a1≤a2
if(a[1]!=-1)dp[1][a[1]][0]=1;
else for(int j=1;j<=200;j++)dp[1][j][0]=1;
ll sum;
for(int i=2;i<=n;i++)
{
sum=0;
for(int j=1;j<=200;j++)
{
if(a[i]==-1 || a[i]==j)dp[i][j][0]=sum;
sum=(sum+dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2])%mod;
}
for(int j=1;j<=200;j++)
if(a[i]==-1 || a[i]==j)dp[i][j][1]=(dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2])%mod;
sum=0;
for(int j=200;j>=1;j--)
{
if(a[i]==-1 || a[i]==j)dp[i][j][2]=sum;
sum=(sum+dp[i-1][j][1]+dp[i-1][j][2])%mod;
}
}
ll ans=0;
for(int j=1;j<=200;j++)ans=(ans+dp[n][j][1]+dp[n][j][2])%mod;//可以理解为>n的位置a[i] (即a[n+1])一定为0,不存在其他可能只可能小于a[n] an≤an−1
printf("%lld\n",ans);
}