出题人的题解还是讲的挺清晰的,emm,为了方便大家理解出题人的题解我解说一下..思路大概就是线性dp+差分,做这个题目的时候没有思路大概就是dp的魅力吧!
下面讲讲怎么做?
题目要求起点和终点同时不能出现两次,用差分思想就是分配括号,相同的括号不能出现两次在同一个地方出现两次,并且括号一定要合法..什么是合法呢?就是(的数量一定大于或者等于)的,不然肯定不行啊..
出题人聚聚说的,我觉得它写的超级棒~
对于每个每个点有4种放置:
放置1:(
放置2:)
放置3:(、)
放置4:什么都不放
然后建立状态dp[i][j]表示到第i个位子,(比)多了j个,使得前i个都等于m?多了多少个(就相当于这个位子可以多少次+1.
先考虑初始赋值..
假如起始位子是a[i]=m-1,dp[1][1]//(比)多1,或者dp[1][0] (和)在同一个位子.都是符合条件的,代码如下:

if(a[i]==m-1) {dp[1][0]=1;dp[1][1]=1;}

假如起始位子是a[i]=m,就dp[1][0]//不放括号,是符合条件的,代码如下:

if(a[i]==m) dp[1][0]=1;

然后考虑状态转移..
位于当前位子的值为ai;
它假如能转移那么它的值只能是有dp[i-1][m-a[i]-1]/dp[i-1][m-a[i]]转移过来,代表这个地方放(/(),或者这个地方放)/或者什么都不放..当然假如这个地方本身>m了,那就没有方案使得成立了..如此推理转态转移就非常好写了..
下面我贴一下转态转移的代码,清结合我说的看一下.

int flag=0;
     for(int i=1;i<=n;i++) if(a[i]>m) flag=1;
     if(flag) cout<<0<<endl;
     else
     {
        for(int i=2;i<=n;i++)
        {
            dp[i][m-a[i]]+=dp[i-1][m-a[i]-1];//自己本身+(
            dp[i][m-a[i]-1]+=dp[i-1][m-a[i]-1]*(m-a[i]);//自己本身+()
            dp[i][m-a[i]]+=dp[i-1][m-a[i]];//什么都不加..
            dp[i][m-a[i]-1]+=dp[i-1][m-a[i]]*(m-a[i]);//加个)
         }
     }

下面贴一下ac代码:

#include<bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb push_back
#define inf 132913423039
typedef long long ll;
const ll mod=998244355;
const ll N=2e3+5;
const ll M=2e4+5;
const double eps=1e-7;
using namespace std;
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b) { return a*b/gcd(a,b);    }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a = (a*a)%p;b >>= 1;}return ans%p;}
ll Inv(ll x)          { return qp(x,mod-2,mod);}
ll C(ll n,ll m){if (m>n) return 0;ll ans = 1;for (int i = 1; i <= m; ++i) ans=ans*Inv(i)%mod*(n-i+1)%mod;return ans%mod;}
ll dp[M][N];
ll a[M];
int main()//要你把n个数->m..
{
     ios;
     ll n,m;
     cin>>n>>m;
     for(ll i=1;i<=n;i++) cin>>a[i];
     ll flag=0;
     for(int i=1;i<=n;i++) if(a[i]>m) flag=1;
     if(a[1]==m-1) {dp[1][0]=1;dp[1][1]=1;}
     if(a[1]==m)    dp[1][0]=1;
     if(flag) cout<<0<<endl;
     else
     {
        for(int i=2;i<=n;i++)
        {
            dp[i][m-a[i]]=(dp[i-1][m-a[i]-1])%mod;//自己本身+(
            dp[i][m-a[i]-1]=(dp[i-1][m-a[i]-1]*(m-a[i]))%mod;//自己本身+()
            dp[i][m-a[i]]=(dp[i][m-a[i]]+dp[i-1][m-a[i]])%mod;//什么都不加..
            dp[i][m-a[i]-1]=(dp[i][m-a[i]-1]+dp[i-1][m-a[i]]*(m-a[i]))%mod;//加个)
        }
     }
     cout<<dp[n][0]<<endl;
     return 0;
}