解题思路
这是一个组合数学问题,需要计算满足以下条件的工作分配方案数:
- 总共
份工作需要完成
- 三位员工分别需要完成
份工作
- 每份工作至少有一个人做,可以多个人合作
- 不同的工作分配方案或不同的人员组合都算作不同方案
解题步骤:
- 首先计算组合数表
,用于后续计算
- 对于第三个人分配的
份工作,我们可以从
份工作中选择
- 对于剩下的工作,需要在第一个人和第二个人之间分配
- 使用动态规划避免重复计算
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MOD = 1000000007;
int main() {
int s, a, b, c;
while (cin >> s >> a >> b >> c) {
vector<int> member = {a, b, c};
sort(member.begin(), member.end());
// 计算组合数表
vector<vector<int>> C(s + 1, vector<int>(s + 1));
C[0][0] = 1;
for (int i = 1; i <= s; i++) {
C[i][0] = 1;
for (int j = 1; j <= s; j++) {
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
}
}
// 计算方案数
int left = s - member[2];
long long ans = 0;
for (int i = 0; i <= left; i++) {
if (i <= member[1] && left - i <= member[0]) {
long long temp = C[member[2]][member[1] - i];
temp = temp * C[left][i] % MOD;
temp = temp * C[s - left + i][member[0] - left + i] % MOD;
ans = (ans + temp) % MOD;
}
}
ans = (ans * C[s][member[2]]) % MOD;
cout << ans << endl;
}
return 0;
}
import java.util.Scanner;
import java.util.Arrays;
public class Main {
static final int MOD = 1000000007;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int s = sc.nextInt();
int[] member = new int[3];
member[0] = sc.nextInt();
member[1] = sc.nextInt();
member[2] = sc.nextInt();
Arrays.sort(member);
// 计算组合数表
int[][] C = new int[s + 1][s + 1];
C[0][0] = 1;
for (int i = 1; i <= s; i++) {
C[i][0] = 1;
for (int j = 1; j <= s; j++) {
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
}
}
// 计算方案数
int left = s - member[2];
long ans = 0;
for (int i = 0; i <= left; i++) {
if (i <= member[1] && left - i <= member[0]) {
long temp = C[member[2]][member[1] - i];
temp = temp * C[left][i] % MOD;
temp = temp * C[s - left + i][member[0] - left + i] % MOD;
ans = (ans + temp) % MOD;
}
}
ans = (ans * C[s][member[2]]) % MOD;
System.out.println(ans);
}
sc.close();
}
}
MOD = 1000000007
while True:
try:
# 读取输入
s, a, b, c = map(int, input().split())
member = sorted([a, b, c])
# 计算组合数表
C = [[0] * (s + 1) for _ in range(s + 1)]
C[0][0] = 1
for i in range(1, s + 1):
C[i][0] = 1
for j in range(1, s + 1):
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD
# 计算方案数
left = s - member[2]
ans = 0
for i in range(left + 1):
if i <= member[1] and left - i <= member[0]:
temp = C[member[2]][member[1] - i]
temp = temp * C[left][i] % MOD
temp = temp * C[s - left + i][member[0] - left + i] % MOD
ans = (ans + temp) % MOD
ans = (ans * C[s][member[2]]) % MOD
print(ans)
except EOFError:
break
算法及复杂度
- 算法:组合数学 + 动态规划
- 时间复杂度:
,其中
为工作总数
- 空间复杂度:
,用于存储组合数表