题解:AtCoder AT_awc0063_c Maximizing Investment
【题目来源】
AtCoder:C - Maximizing Investment
【题目描述】
Takahashi is investing in \(N\) stocks. The current asset value of stock \(i\) (\(1 \leq i \leq N\)) is \(S_i\).
高桥正在投资 \(N\) 只股票。股票 \(i\)(\(1 \leq i \leq N\))的当前资产价值为 \(S_i\)。
Takahashi will now perform the following operation exactly \(K\) times.
高桥现在将恰好执行 \(K\) 次以下操作。
- Choose one of the \(N\) stocks and double its current asset value.
从 \(N\) 只股票中选择一只,并将其当前资产价值翻倍。
He may freely choose which stock to select for each operation, and the same stock may be chosen multiple times. If the same stock is chosen multiple times, the doubling operation is applied cumulatively each time. For example, if a stock with asset value \(S\) is chosen \(3\) times, its asset value becomes \(2^3 \times S = 8S\).
他每次操作可以自由选择哪只股票,同一只股票可以被选择多次。如果同一只股票被选择多次,每次都会应用翻倍操作累积计算。例如,如果一只资产价值为 \(S\) 的股票被选中 \(3\) 次,其资产价值变为 \(2^3 \times S = 8S\)。
Takahashi wants to maximize the total asset value of all \(N\) stocks after performing all \(K\) operations.
高桥希望在执行完所有 \(K\) 次操作后,最大化所有 \(N\) 只股票的总资产价值。
When the choice of stocks for the operations is made optimally, find the maximum possible total asset value of the \(N\) stocks after \(K\) operations. Since the answer can be very large, output the maximum total modulo \(10^9 + 7\).
当操作中选择的股票最优时,求 \(K\) 次操作后 \(N\) 只股票可能的最大总资产价值。由于答案可能非常大,输出对 \(10^9 + 7\) 取模的最大总和。
【输入】
\(N\) \(K\)
\(S_1\) \(S_2\) \(\ldots\) \(S_N\)
- The first line contains an integer \(N\) representing the number of stocks and an integer \(K\) representing the number of operations, separated by a space.
- The second line contains integers \(S_1, S_2, \ldots, S_N\) representing the asset values of each stock before the operations, separated by spaces.
【输出】
Output in one line the maximum total asset value of the \(N\) stocks when the \(K\) operations are performed optimally, modulo \(10^9 + 7\).
【输入样例】
3 2
1 3 2
【输出样例】
15
【核心思想】
-
问题分析:给定 \(N\) 只股票的初始资产 \(S_i\),恰好进行 \(K\) 次翻倍操作,每次任选一只股票将其当前价值翻倍。目标是最大化 \(K\) 次操作后的总资产。由于翻倍操作的收益取决于被操作股票的当前价值,而当前价值最大的股票每次翻倍带来的增量最大,因此所有 \(K\) 次操作都应集中在初始最大值上。
-
算法选择:
- 贪心策略:每次选择当前资产最大的股票进行翻倍,最终最优策略是将全部 \(K\) 次操作都作用于初始最大值 \(S_{\max}\)
- 快速幂(Binary Exponentiation):计算 \(2^K \bmod (10^9+7)\),将 \(K\) 次翻倍的效果用 \(O(\log K)\) 时间聚合为乘法因子
-
关键步骤:
- 读取输入:\(N\)、\(K\) 和数组 \(S_{1..N}\)
- 求和并找最大值:累加所有股票资产得到 \(sum\),同时找出最大值 \(S_{\max}\)
- 计算除最大值外的和:\(others = sum - S_{\max}\)
- 快速幂计算翻倍因子:\(mul = 2^K \bmod (10^9+7)\)
- 输出答案:\((others + S_{\max} \times mul) \bmod (10^9+7)\)
-
时间/空间复杂度:
- 时间复杂度:\(O(N + \log K)\),遍历数组 \(O(N)\),快速幂 \(O(\log K)\)
- 空间复杂度:\(O(1)\),仅使用常数个额外变量
-
贪心 + 快速幂的核心思想:
- 局部最优即全局最优:每次选择当前最大值翻倍,总资产的增量最大;由于每次操作后该股票仍是最大值,贪心策略可延伸至全部 \(K\) 次操作
- 操作聚合:将同一只股票上的 \(K\) 次连续翻倍聚合为乘以 \(2^K\),避免逐次模拟
- 模意义下的快速幂:利用二进制拆分将幂运算降至对数时间,适用于大指数模运算
- 适用于带选择权的重复增益最大化问题
【算法标签】
快速幂
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long // 定义int为long long类型
const int N = 200005, p = 1e9 + 7; // 常量定义
int n, k, maxn = -1; // n: 数组长度, k: 操作次数, maxn: 最大值
int s[N], sum; // s: 数组(未实际使用), sum: 除最大值外的和
// 快速幂计算 a^b mod p
int qmi(int a, int b)
{
int mul = 1; // 结果初始化为1
while (b) // 当b不为0
{
if (b & 1) // 如果b的二进制最后一位是1
{
mul = mul * a % p; // 累乘当前a
}
a = a * a % p; // a自乘
b /= 2; // b右移一位(等价于b >>= 1)
}
return mul; // 返回结果
}
signed main()
{
cin >> n >> k; // 输入数组长度n和操作次数k
for (int i = 1; i <= n; i++)
{
int x;
cin >> x; // 输入数组元素
maxn = max(maxn, x); // 更新最大值
sum += x; // 累加所有元素的和
}
sum -= maxn; // 减去最大值,得到除最大值外的和
// 计算结果:sum + 2^k * maxn
cout << (sum + qmi(2, k) * maxn) % p << endl;
return 0; // 程序正常结束
}
【运行结果】
3 2
1 3 2
15
浙公网安备 33010602011771号