洛谷P4369

题目链接:洛谷P4369 [Code+#4]组合数问题

题意大意

给你一个数 \(x\) , 要求写成 \(k\) 个组合数的和, 且要求: \(C_n^m\) 中 $ 0 \leqslant m \leqslant n \leqslant x$

即:我们要找到 \(k\) 个组合数,让他们的和等于 \(x\).

分析

我们观察到数据范围,不可能让你写暴力, 所以我们就要考虑有没有规律了

然后我们列出组合数

n = 0              1
n = 1            1   1
n = 2          1   2   1
n = 3        1   3   3   1
n = 4      1   4   6   4   1
n = 5    1   5   10  10  5   1
n = 6  1   6   15  20  15  6   1

我们知道 \(C_n^0 = C_n^n = 1\), \(C_n^1 = C_n^{n - 1} = n\)

然后题目中说任意一组解即可,那我们又可以玩点奇怪的了/xyx

\(x = \sum\limits_{i = 1}^{k - 1}1 + (x - k + 1)\)
$\ \ \ \ \sum\limits_{i = 1}^{k - 1}C_i^0 + C_{x - k + 1}^1 $

题目中说,不可以相同, 但是只要 \(n\) 或者 \(m\) 不相同就行了,我们上面的式子是没有 \(n\)\(m\) 都相同的情况的,所以我们可以大胆使用(幸亏有SPJ)

当然方式有很多种,也可以自己尝试,反正我觉得这种最简单

code:

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>

#define int long long
#define rr register

#define inf 1e9
#define MAXN 100010

using namespace std;

inline int read() {
	int s = 0, f = 0;
	char ch = getchar();
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

void print(int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) print(x / 10);
	putchar(x % 10 + 48);
}

int x, k;

signed main() {
	x = read();
	k = read();
	for (rr int i = 1; i <= k - 1; i++) cout << i << " " << 0 << "\n";
	cout << x - k + 1 << " " << 1 << "\n";
}
posted @ 2020-08-24 21:08  Aliemo  阅读(168)  评论(2编辑  收藏  举报