#include using namespace std; typedef long long LL; const int N = 1000010; int n, p; // n个小朋友,模p LL f[N]; // DP数组,前序最大子段和 int main() { cin >> n >> p; // n个小朋友,模p LL s = 0, mx = -1e18; for (int i = 1; i <= n; i++) { int x; cin >> x; s = max(s, 0ll) + x; // 最大子段和的套路,如果能继承父亲的财产就继承,如果父亲只有债务,就不管 mx = max(mx, s); // 到i为止可以获得的最大子段和 f[i] = mx; // 保存到dp数组f[N]中 } /* ① 每个小朋友的特征值等于排在他前面(包括他本人)的小朋友中连续若干个 (最少有一个)小朋友手上的数字之和的最大值。 ② 第一个小朋友的分数是他的特征值, 其它小朋友的分数为排在他前面的所有小朋友中(不包括他本人),小朋友分数加上其特征值的最大值。  */ LL res = f[1]; // 第一个小朋友的得分目前是大王 LL score = f[1] * 2; // 第二个小朋友的得分 = 第一个小朋友的得分+第一个小朋友的特征值 for (int i = 2; i <= n; i++) { // 从第二个小朋友开始,到最后一个小朋友枚举 res = max(res, score); // res:记录最大分数 if (f[i] > 0) score += f[i]; // 如果最大子段和大于0,可以接在后面 } printf("%lld\n", res % p); // 对p取模输出 return 0; }