题目大意
给出四个整数:A,B,K,C,A,B,C 都是大于 0 的个位数,问在所有仅由 A 或 B 组成的 K 位数中(K 位数的每一位都是 A 或 B),数字 C 的个数有多少
题解
- 分析样例 1 2 3 2
- 根据题目我们推出样例中所有的 3 位数为:
共 0 个 2
共 3 个 2
共 6 个 2
共 3 个 2 - 所以本题答案为: 。
- 考虑除 111 的其他数字,第二行的数中每个数都包含一个二,也就是说,第二行的数都是 从 3 位数的其中一位将其设为 2,很明显可以联想到组合数。
- 从三个位置选一个位置为 2 的所有情况,这种数的个数 C(3,1),然后每个数都有一个 2,所以答案为 C(3,1)*1,所以第 三行为 C(3,2)*2,第三行为 C(3,3)*3。
- 所以可以推出,最终答案为 。
- 求组合数的公式为:
- 但是题目要求对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;
}