题目## 题目
解题思路
这是一个数组划分问题,需要找到一个位置K,使得左右两部分的最大值之差的绝对值最大。
算法步骤:
-
找到数组的最大值:
- 记录最大值和它的位置。
-
遍历所有可能的划分点:
- 对于每个划分点 K K K(从 0 0 0 到 N − 2 N-2 N−2):
- 计算左部分 [ 0.. K ] [0..K] [0..K] 的最大值
- 计算右部分 [ K + 1.. N − 1 ] [K+1..N-1] [K+1..N−1] 的最大值
- 计算两部分最大值的差的绝对值
-
更新最大差值:
- 记录所有划分方案中的最大差值。
代码
class MaxGap {
public:
int findMaxGap(vector<int>& A, int n) {
if (n <= 1) return 0;
int maxGap = 0;
// 遍历所有可能的划分点
for (int k = 0; k < n - 1; k++) {
// 计算左部分最大值
int leftMax = A[0];
for (int i = 0; i <= k; i++) {
leftMax = max(leftMax, A[i]);
}
// 计算右部分最大值
int rightMax = A[k + 1];
for (int i = k + 1; i < n; i++) {
rightMax = max(rightMax, A[i]);
}
// 更新最大差值
maxGap = max(maxGap, abs(leftMax - rightMax));
}
return maxGap;
}
};
import java.util.*;
public class MaxGap {
public int findMaxGap(int[] A, int n) {
if (n <= 1) return 0;
int maxGap = 0;
// 遍历所有可能的划分点
for (int k = 0; k < n - 1; k++) {
// 计算左部分最大值
int leftMax = A[0];
for (int i = 0; i <= k; i++) {
leftMax = Math.max(leftMax, A[i]);
}
// 计算右部分最大值
int rightMax = A[k + 1];
for (int i = k + 1; i < n; i++) {
rightMax = Math.max(rightMax, A[i]);
}
// 更新最大差值
maxGap = Math.max(maxGap, Math.abs(leftMax - rightMax));
}
return maxGap;
}
}
class MaxGap:
def findMaxGap(self, A, n):
if n <= 1:
return 0
max_gap = 0
for k in range(n - 1):
# left part max
left_max = max(A[:k + 1])
# right part max
right_max = max(A[k + 1:])
# update max gap
max_gap = max(max_gap, abs(left_max - right_max))
return max_gap
算法及复杂度
- 算法:遍历 + 最大值计算
- 时间复杂度: O ( n 2 ) \mathcal{O(n^2)} O(n2),需要遍历所有划分点,每次都要计算左右部分的最大值
- 空间复杂度: O ( 1 ) \mathcal{O(1)} O(1),只使用常数额外空间
解题思路
这是一个组合数学问题,需要计算满足以下条件的工作分配方案数:
- 总共 s s s 份工作需要完成
- 三位员工分别需要完成 a , b , c a, b, c a,b,c 份工作
- 每份工作至少有一个人做,可以多个人合作
- 不同的工作分配方案或不同的人员组合都算作不同方案
解题步骤:
- 首先计算组合数表 C [ i ] [ j ] C[i][j] C[i][j],用于后续计算
- 对于第三个人分配的 c c c 份工作,我们可以从 s s s 份工作中选择
- 对于剩下的工作,需要在第一个人和第二个人之间分配
- 使用动态规划避免重复计算
代码
#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
算法及复杂度
- 算法:组合数学 + 动态规划
- 时间复杂度: O ( s 2 ) \mathcal{O}(s^2) O(s2),其中 s s s 为工作总数
- 空间复杂度: O ( s 2 ) \mathcal{O}(s^2) O(s2),用于存储组合数表
318

被折叠的 条评论
为什么被折叠?



