题意:给定n和m,计算符合如下条件的数列个数对998244353取模,
1.数列含有n个元素
2.数列中每个元素从1到m
3.数列是单峰数列【存在位置k,从1到k严格递增,从k到n严格递减】
4.数列中有且仅有一对相等的数
思路:
数列有一对相同的元素,所以是n-1个不同的数,所以峰值取值[n-1,m],并且相同的数只能分别在峰值两边
枚举放入峰值 i∈[n-1,m],然后还应该从i-1个数里取(n-2)个不同的数+一个和这(n-2)个数里相同的数,有 种取法
然后现在就看放入i后,任意取出的n-2 +1个数的排列
①峰值k前面放1个数时,剩余的数+选一个和前面相同的数 放峰值后面,相同的数有1种选择,即 * 1
②峰值k前面放2个数时,剩余的数+选一个和前面相同的数 放峰值后面,相同的数有2种选择,即 * 2
…峰值k前面放(n-2)个数时,剩余的数(无)+选一个和前面相同的数 放峰值后面,相同的数有(n-2)种选择,即 * (n-2)
所以共有 * 1 + * 2 + … + * (n-2)种排列
所以 Ans=∑ * ( * 1 + * 2 + … + * (n-2) )
官方题解的式子是 * (n-2) * 2n-3
即 = ∑ ,(n-2) * 2n-3 = ( * 1 + * 2 + … + * (n-2) )
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll p=998244353;
ll n,m,ans,f[200007];
ll qpow(ll x,ll e,ll mod){
ll re=1;
while(e){
if(e&1){
re=re*x%mod;
}
x=x*x%mod;
e>>=1;
}
return re%mod;
}
ll C(ll a,ll b){
ll re,up,down;
up=f[a];
down=f[b]*f[a-b]%p;
re=up*qpow(down,p-2,p)%p;
return re;
}
int main(){
cin>>n>>m;
f[0]=f[1]=1;
for(int i=2;i<=max(n,m);i++)f[i]=f[i-1]*i%p;
ll t=0;
for(int i=1;i<=n-2;i++)
t=(t+C(n-2,i)*i)%p;
for(int i=n-1;i<=m;i++)
ans=(ans+C(i-1,n-2))%p;
ans=ans*t%p;
cout<<ans;
}