[Codeforces 1312D] Count the Arrays //组合数学

题目链接

题意:给定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)个数里相同的数,有 C i 1 n 2 C^{n-2}_{i-1} 种取法
然后现在就看放入i后,任意取出的n-2 +1个数的排列
①峰值k前面放1个数时,剩余的数+选一个和前面相同的数 放峰值后面,相同的数有1种选择,即 C n 2 1 C^{1}_{n-2} * 1
②峰值k前面放2个数时,剩余的数+选一个和前面相同的数 放峰值后面,相同的数有2种选择,即 C n 2 2 C^{2}_{n-2} * 2
…峰值k前面放(n-2)个数时,剩余的数(无)+选一个和前面相同的数 放峰值后面,相同的数有(n-2)种选择,即 C n 2 n 2 C^{n-2}_{n-2} * (n-2)
所以共有 C n 2 1 C^{1}_{n-2} * 1 + C n 2 2 C^{2}_{n-2} * 2 + … + C n 2 n 2 C^{n-2}_{n-2} * (n-2)种排列
所以 Ans=∑ n 1 m ^{m}_{n-1} C i 1 n 2 C^{n-2}_{i-1} * ( C n 2 1 C^{1}_{n-2} * 1 + C n 2 2 C^{2}_{n-2} * 2 + … + C n 2 n 2 C^{n-2}_{n-2} * (n-2) )

官方题解的式子是 C m n 1 C^{n-1}_{m} * (n-2) * 2n-3
C m n 1 C^{n-1}_{m} = ∑ n 1 m ^{m}_{n-1} C i 1 n 2 C^{n-2}_{i-1} ,(n-2) * 2n-3 = ( C n 2 1 C^{1}_{n-2} * 1 + C n 2 2 C^{2}_{n-2} * 2 + … + C n 2 n 2 C^{n-2}_{n-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;
}

猜你喜欢

转载自blog.csdn.net/qq_45530271/article/details/104778448