kuangbin 数学训练二 Arrange the Numbers

题目链接:
传送门

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N = 1010;
const ll p = 1000000007;
ll t, n, m, r, ca;
ll fact[N], infact[N], d[N];

//快速幂模板
ll qmul(ll a, ll k) {
	ll res = 1;
	while (k) {
		if (k & 1) res = res * a % p;
		a = (ll)a * a % p;
		k >>= 1;
	}
	return res;
}

int main() {
	fact[0] = infact[0] = 1;
	d[0] = 1;
	d[1] = 0;
	//所有数的阶乘及其逆元打表
	for (ll i = 1; i < N; i++) {
		fact[i] = fact[i - 1] * i % p;
		infact[i] = infact[i - 1] * qmul(i, p - 2) % p;
	}
	//n个数全错排数的打表
	for (ll i = 2; i < N; i++) {
		d[i] = (d[i - 1] + d[i - 2]) % p * (i - 1) % p;
	}
	scanf("%lld", &t);
	while(t--) {
		scanf("%lld%lld%lld", &n, &m, &r);
		ll ans = 0;
		ll q = n - m;
		//枚举所有错排的情况
		for (ll i = 0; i <= q; i++) {
			ll c = fact[q] * infact[i] % p * infact[q - i] % p;
			ans = (ans + c * d[n - r - i]) % p;
		}
		//最后乘上固定不动的组合数
		ans = ans * (fact[m] * infact[r] % p * infact[m - r] % p) % p;
		printf("Case %lld: %lld\n", ++ca, ans);
	}
}

这道题是组合数加上全错排的一个应用
首先打表求出所有数字的阶乘及其阶乘的逆元,以方便后面求组合数
接着打表求出n个数字的全错排数
最后枚举所有错排情况,即m - k个必须错排,后面n - m个数可错排,可不错排。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值