C. Two Arrays(1288C)(组合数)

C. Two Arrays(1288C)(组合数)


题目来源:C. Two Arrays


题意:

给出 n 和 m,构造两个数组 a 和 b,满足以下条件

  • 数组长度均为 m
  • 两数组的值域为 1 - n
  • a 数组按非降序排序
  • b 数组按非升序排序
  • a[i] <= b[i]

思路:

根据题意我们可以知道,a升序,b降序,并且 a[1] >= b[1],那么我们可以将b数组翻转一下,并将它们连接起来

将新的两个数组先连接起来组成 b[m], b[m - 1], … , b[1], a[1], a[2], … , a[m],此时的数组是非降序的

此时相当于在 1 - n 中选出 2 * m 个数,并且每个数可以被选多次
反向思考一下,就变成将 2 * m 个球投入 n 个篮子里,篮子允许为空
先让每个篮子至少拥有一个球
问题就变成了将 2 * m + n 个球投入 n 个篮子里,每个篮子至少有一个球
利用隔板法,将 n - 1 个板插入 2 * m + n - 1 个空隙中
因此答案为 C(2 * m + n - 1, n - 1)

思路来源
  • 最后为什么直接插板就行,而不用考虑排序的问题(从前往后插板所隔开的球不能减少)
    • 因为我们构成的新数组数非递减的,所以我们只需要找出 2 * m 个数即可,将它们存入新数组时,就相当于会自动排序了

AC代码

#include <bits/stdc++.h>
#define endl "\n"
#define rep(i, m, n) for (int i = (m); i <= (n); ++i)
#define rrep(i, m, n) for (int i = (m); i >= (n); --i)
#define IOS ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e3 + 50, mod = 1e9 + 7;
int n, m;
// 2 * m + n 个球,放入 n 个盒子,每个盒子至少一个
// 插板法相当于有 2 * m + n - 1 个空,插 n - 1 个板
// C(2 * m + n - 1, n - 1) = (2 * m + n - 1)! / (n - 1)! / (2 * m)!
ll qpow(int a, int b) {
	ll res = 1; a %= mod;
	while (b) {
		if (b & 1) res = (ll)res * a % mod;
		a = (ll)a * a % mod; b >>= 1;
	}
	return res;
}
ll C(int a, int b) {
	ll up = 1, down = 1;
	for (int i = 0; i < b; ++i) {
		up = up * (a - i) % mod;
		down = down * (b - i) % mod;
	}
	down = qpow(down, mod - 2); // 计算逆元
	return up * down % mod;
}
void solve() {
	cin >> n >> m;
	cout << C(2 * m + n - 1, n - 1) << endl;
}
int main() {
	solve();
	return 0;
}

END

好的,以下是示例代码: ```c #include <stdio.h> #include <stdbool.h> #define MAX_SIZE 100 typedef struct { int nums[MAX_SIZE]; int length; } CheckDuplicate; bool check(CheckDuplicate *checker) { bool seen[MAX_SIZE] = {false}; for (int i = 0; i < checker->length; i++) { if (seen[checker->nums[i]]) { return true; } seen[checker->nums[i]] = true; } return false; } int main() { int nums1[] = {1, 2, 3, 4, 5, 6, 7}; CheckDuplicate checker1 = {nums1, 7}; printf("%s\n", check(&checker1) ? "true" : "false"); // false int nums2[] = {1, 2, 3, 4, 5, 6, 7, 7}; CheckDuplicate checker2 = {nums2, 8}; printf("%s\n", check(&checker2) ? "true" : "false"); // true return 0; } ``` 以上代码定义了一个 `CheckDuplicate` 结构体,该结构体包含一个整数数组 `nums` 和数组长度 `length`。`check` 函数用于检查整数数组中是否有重复数字,如果有则返回 `true`,否则返回 `false`。 在 `check` 函数中,使用了一个布尔型数组 `seen` 来记录已经出现过的数字。遍历整数数组,如果当前数字已经在 `seen` 数组中出现过,则说明有重复数字,直接返回 `true`。如果遍历完整个整数数组仍然没有找到重复数字,则返回 `false`。 在示例代码中,我们先创建两个整数数组,一个有重复数字,一个没有重复数字。然后分别使用 `CheckDuplicate` 结构体来检查这两个整数数组,最终输出结果。 希望这个示例代码能够帮到你,如果你有任何问题或者需求,可以随时告诉我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值