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;
|
|||
|
|
}
|