CF-Round 83-Div. 2-D题

CF-Round 83-Div. 2-D题

D. Count the Arrays

传送门

这道题就是问你有多少个满足要求的序列。跟上次一道题比较像。要求序列中存在一对相等的数,然后序列满足这样的要求,先是严格递增,然后严格递减。
然后问你存在多少个取模。

这道题是组合逆元问题。
还挺简单的把。。。(我没有膨胀。。)
我们这样考虑。因为存在一对相等的数字。所以有n-1个数字是不一样的,我们需要从m个数字中选择n-1个不一样的数字。组合问题把。。就是C(m, n-1)
然后这n-1个数字中选择一个数字进行重复。
这个地方我们 不能选择最大的数字,如果选择最大的数字的话。。那就不能进行严格递增然后严格递减的要求了。
所以我们有n-2个选择(排除最大的数字)
再考虑分布问题。题目没说最大的数字要在中间把。
所以最大数字的左边和右边是没有限制的。
我们考虑到这n个数字中有两个数字相同,必须摆放到最大数字的左边和右边。剩余还有n-3个数字。(这n-3个数字互不相同)每个数字有两种选择,选择左边或者右边。所以是2^(n-3)。
然后乘起来就是答案了。
C(m, n-1) (n-2) 2^(n-3)
注意每一步都要取模。
取模之后的数字可能发生变化不是原来的操作了。。
所以费马来啦。
这里的n可以达到2e5。所以乘法逆元
求组合数的时候也需要逆元。(原因上面我说过啦~)

代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int N = 2e5 + 10;

int n, m;
ll fact[N];

void solve()
{
	fact[0] = 1;
	for (int i = 1; i < N; i++)
	{
		fact[i] = fact[i - 1] * i % mod;
	}
}

ll npower(ll a, ll b)
{
	ll res = 1;
	while (b)
	{
		if (b & 1)
		{
			res = res * a % mod;
		}
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

ll C(int a, int b)
{
	ll res1 = fact[b] * fact[a - b] % mod;
	res1 = npower(res1, mod - 2);
	return fact[a] * res1 % mod;
}

int main()
{
	solve();
	cin >> n >> m;
	ll ans = 0;
	if (n > 2)
	{
		ll ans1 = npower(2, n - 3) % mod;
		ll ans2 = C(m, n - 1);
		ans = (ans1 * ans2 % mod) * (n - 2) % mod;
	}
	cout << ans << endl;
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃酱斯密酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值