Educational Codeforces Round 83-D. Count the Arrays

题目传送门:D. Count the Arrays

在这里插入图片描述
input

3 4

output

6

input

3 5

output

10

input

42 1337

output

806066790

input

100000 200000

output

707899035

样例1解释
题意:给你n,m;
让你构造一个长度为n的数列,要下面满足几个条件
1.保证数列中所有的数都在1~m中,而且有且只有一个数出现过两次,其余数最多只能出现一次。
2.数列中有一个要有这样一个位置i,在i之前的要严格单调增,在i之后的要严格单调递减。俗话说就是要有个尖尖。
问:能构造多少种不同的数列?
思路:
实现我们要从m个数中选出(n-1)个数,(因为有一个数重复)方式有 C ( m , n 1 ) C(m,n-1) 表示组合数。然后我们要确定那个重复的数是谁,一共(n-1)个不同的数,因为不能是最大值,所以我们还有(n-2)种情况去选,最后我们已经知道我们选的那个最大值就是那个尖尖,还有两个数和那个最大值的相对位置也固定了,就是一边一个,然后其余的(n-3)个数每个数我们有两种选择,放在那个尖尖的左边还是右边。一共有2(n-3)
所以最后答案就算 a n s = C m , n 1 ) ( n 2 ) 2 ( n 3 ) ans=C(m,n-1)*(n-2)*2 ^( n^-3^)
AC

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<vector>
#include<map>
#include<iostream>
using namespace std;
#define LL long long
#define PI acos(-1.0)
const LL N=2e5+10;
LL mod=998244353;
LL ksm(LL a,LL b)
{
    LL ans=1;
    while(b)
    {
        if(b&1)
        {
            ans*=a;
            ans%=mod;
        }
        a*=a;
        a%=mod;
        b/=2;
    }
    return ans;
}
int main()
{
    LL n,m;
    cin>>n>>m;
    if(n==2)
    {
        cout<<"0"<<endl;
    }
    else
    {
        LL as1=1,as2=1;
        for(int i=1;i<=n-1;i++)
        {
            as1=as1*(m-i+1);
            as1%=mod;
            as2=as2*i;
            as2%=mod;
        }
        cout<<(((as1*ksm(as2,mod-2))%mod*(n-2))%mod*ksm(2,n-3))%mod<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43402296/article/details/106319997