CodeForces 1312D. Count the Arrays【数学题】

传送门

题意

算一下有多少个满足以下要求的排列:

  • 长为 \(n\)
  • 每个元素在 \([1,m]\)
  • 有且仅有 \(1\) 对元素相等
  • 存在第 \(k\) 位满足 \(a_1<a_2<...<a_k,a_k>a_{k+1}>...>a_n\)

题解

一个排列中一共有 \(n-1\) 个不同的数。所以可以有 \(C_m^{n-1}\) 种选法。
最大的数作为 \(a_k\) 然后这 \(n-2\) 个数中可以任选 \(i\) 个数放在 \(a_k\) 的左边,剩余的放在右边,这里就又有 \(C_{n-2}^i\) 种选法,
然后再在左边的 \(i\) 个数中随便选一个加在右边,又有 \(i\) 种选法。
所以答案为 \(C_m^{n-1}\cdot \sum_{i=1}^{n-2}C_{n-2}^{i}\cdot i\)

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ff first
#define ss second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=2e5+10;
const int M=1e6+10;
const LL mod=998244353;
int n,m;
LL inv[N],invf[N],fac[N],po[N];
 
LL C(int n,int m){
    if(m>n) return 0;
    return fac[n]*invf[m]%mod*invf[n-m]%mod;
}
 
int main(){
    scanf("%d%d",&n,&m);
    invf[0]=inv[0]=invf[1]=inv[1]=po[0]=fac[0]=1;
    for(int i=2;i<=max(n,m);i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    for(int i=2;i<=max(n,m);i++) invf[i]=invf[i-1]*inv[i]%mod;
    for(int i=1;i<=max(n,m);i++) po[i]=po[i-1]*2%mod,fac[i]=fac[i-1]*i%mod;
    LL ans=0,temp=0;
    for(int i=1;i<=n-2;i++) temp=(temp+C(n-2,i)*i%mod)%mod;
    ans=C(m,n-1)*temp%mod;
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BakaCirno/p/12462735.html