#include // 使用标准命名空间 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; }