CTU Open Contest 2019.A——Beer Barrels【组合数 & 乘法逆元】

题目大意

给出四个整数:A,B,K,C,A,B,C 都是大于 0 的个位数,问在所有仅由 A 或 B 组成的 K 位数中(K 位数的每一位都是 A 或 B),数字 C 的个数有多少


题解

  • 分析样例 1 2 3 2
  • 根据题目我们推出样例中所有的 3 位数为:
    111                     111\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | 共 0 个 2
    211    121    112     211 \ \ 121 \ \ 112\ \ \ | 共 3 个 2
    221    212    122     221 \ \ 212 \ \ 122\ \ \ | 共 6 个 2
    222                     222 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ | 共 3 个 2
  • 所以本题答案为: 0 + 3 + 6 + 3 = 12 0+3+6+3=12
  • 考虑除 111 的其他数字,第二行的数中每个数都包含一个二,也就是说,第二行的数都是 从 3 位数的其中一位将其设为 2,很明显可以联想到组合数。
  • 从三个位置选一个位置为 2 的所有情况,这种数的个数 C(3,1),然后每个数都有一个 2,所以答案为 C(3,1)*1,所以第 三行为 C(3,2)*2,第三行为 C(3,3)*3。
  • 所以可以推出,最终答案为 Σ C ( K i ) i i [ 1 K ] ΣC(K,i)*i,i∈[1,K]
  • 求组合数的公式为:
    C n m = P n m P m = n ! m ! ( n m ) ! , C n 0 = 1 C_{n}^{m}=\frac{P_{n}^{m}}{P_m}=\frac{n!}{m!(n-m)!},C_{n}^{0}=1
  • 但是题目要求对1e9+7取模,每个阶乘都是模过的,需要用快速幂求下逆元就好

AC-Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const ll mod = 1e9 + 7;

ll q_pow(ll a, ll b, ll mod) { // 快速幂
	ll res = 1LL;
	while (b) {
		if (b & 1)	res = (res * a) % mod;
		a = (a * a) % mod;
		b >>= 1;
	}
	return res % mod;
}

ll f[1007]; // 阶乘表
ll inv(ll x) {
	return q_pow(x, mod - 2, mod);
}
int main() {
	f[0] = f[1] = 1;
	for (int i = 2; i <= 100; ++i)	f[i] = (f[i - 1] * i) % mod;
	ll a, b, k, c;	while (cin >> a >> b >> k >> c) {
		ll ans = 0;
		if (a == b && a == c) // a=b=c
			ans = k;
		else if (a != b && (a == c || b == c)) {
			for (int i = 1; i <= k; ++i) {
				ll tmp = (f[k] * inv(f[i]) * inv(f[k-i])) % mod; // 除法改为乘法逆元
				ans = (ans + tmp * i) % mod; // 每种情况有i个所求数字
			}
		}
		cout << ans << endl;
	}

	return 0;
}

发布了203 篇原创文章 · 获赞 130 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/104463939