64 lines
1.9 KiB
C++
64 lines
1.9 KiB
C++
#include <bits/stdc++.h>
|
||
|
||
// 使用标准命名空间
|
||
using namespace std;
|
||
|
||
// 定义__int128类型为LL,用于处理大数避免溢出
|
||
typedef __int128 LL;
|
||
|
||
// 定义常量N为1e6+10,适应题目数据范围
|
||
const int N = 1000010;
|
||
|
||
// 全局变量
|
||
int n, p; // n:小朋友数量 p:模数
|
||
LL f[N]; // f[i]:前i个小朋友的特征值(最大子段和)
|
||
|
||
// 自定义max函数,处理__int128类型
|
||
LL max(LL a, LL b) {
|
||
if (a >= b) return a;
|
||
return b;
|
||
}
|
||
|
||
int main() {
|
||
// 读取输入n和p
|
||
cin >> n >> p;
|
||
|
||
// 初始化变量
|
||
LL s = 0; // s:当前子段和
|
||
LL mx = -1e36; // mx:到目前为止的最大子段和
|
||
|
||
// 计算每个小朋友的特征值f[i]
|
||
for (int i = 1; i <= n; i++) {
|
||
int x; // 当前小朋友的数字
|
||
cin >> x;
|
||
|
||
// Kadane算法计算最大子段和
|
||
// 如果前面的子段和s为负,则舍弃,重新开始计算
|
||
s = max(s, 0) + x;
|
||
// 更新到目前为止的最大子段和
|
||
mx = max(mx, s);
|
||
// 保存前i个小朋友的特征值
|
||
f[i] = mx;
|
||
}
|
||
|
||
// 计算分数并找到最大值
|
||
LL res = f[1]; // res:记录最大分数,初始化为第一个小朋友的分数
|
||
LL score = f[1] * 2; // score:当前可转移的最大分数值
|
||
// 初始化为第一个小朋友分数的两倍,这是第二个小朋友可能获得的最大分数
|
||
|
||
// 遍历所有小朋友计算分数
|
||
for (int i = 2; i <= n; i++) {
|
||
// 更新最大分数
|
||
res = max(res, score);
|
||
|
||
// 如果当前特征值f[i]为正,则加入score,这样后续分数会更大
|
||
// 因为对于i+1到n的小朋友来说,选择i作为前面的小朋友时,分数会更大
|
||
if (f[i] > 0)
|
||
score += f[i];
|
||
}
|
||
|
||
// 输出结果:最大分数对p取模
|
||
printf("%lld\n", res % p);
|
||
|
||
return 0;
|
||
} |