这题主要就是涉及到满足条件的组合数,

思路:从m个数中选择n-1个不同的数。由于里面的元素只有一个重复,而且重复的元素不能是最大值,那么就要从剩下的n-2个数中选择出一个最大值,下标为i。对于剩下的n-3个数,选x个排在最大值的左侧,这样的话,总共的情况数就是

C(n-1,m)*(n-2)*(2^(n-3))

那么代码就很简单了。但是问题来了,这个组合数会很大,要模除一个数。然后由于同余线性方程组没有除法,因此组合数要取逆元,也就是a^-1=a^(p-2)

求逆元的话就可以用快速幂来求,然后就是看代码了

需要特别注意的是,当n=2的时候,无法满足要求,以及n-1>m的时候,也是无法满足要求的。

#include <iostream>
#include <math.h>
using namespace std;
typedef long long ll;

const ll md = 998244353;
#define MAXN 200010

ll fact[MAXN];

ll qpow(ll x, ll k)
{
    ll ans = 1;
    x %= md;
    while (k)
    {
        if (k & 1)
            ans = (ans * x) % md;

        x = (x * x) % md;
        k >>= 1;
    }
    return ans%md;
}

ll c(ll a, ll b) //C(a,b)
{
    return 1ll*(fact[a] * qpow((fact[b] * fact[a - b]) % md, md - 2)) % md; //模意义下的组合数,分母要取逆元
}

int main()
{
    ll n, m;
    cin >> n >> m;

    if (n == 2 || n - 1 > m)
    {
        cout << 0 << endl;
        return 0;
    }

    fact[0] = 1;
    for (int i = 1; i <= 200000; ++i)
        fact[i] = (i * fact[i - 1]) % md;

    ll ans1 = c(m, n - 1);
    ll ans2 = n - 2;
    ll ans3 = qpow(2, n - 3);

    ll ans = (ans1 * ans2) % md;
    ans = (ans*ans3)%md;
    cout << ans << endl;
}

欢迎关注我的公众号“灯珑”,让我们一起了解更多的事物~

你也可能喜欢

发表评论