看不懂题,就不能写的稍微像人话点吗我去。。。
题目就是要找一段区间使得Σai mod m的值最大。
于是嘛。。。前缀和一下再贪心就好了。
先求出前i个数的前缀和s,然后用s更新解。
还有可能就是前面的某个前缀和s1刚好在mod m意义下大于s且是最小的一个,那么这一段的和就是m + s - s1,再用它来更新解。
1 /************************************************************** 2 Problem: 3544 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:2056 ms 7 Memory:7012 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 #include <set> 13 14 using namespace std; 15 typedef long long ll; 16 int n; 17 ll mod, s, a, ans, p; 18 set <ll> S; 19 20 inline ll read(){ 21 ll x = 0, sgn = 1; 22 char ch = getchar(); 23 while (ch < '0' || ch > '9'){ 24 if (ch == '-') sgn = -1; 25 ch = getchar(); 26 } 27 while (ch >= '0' && ch <= '9'){ 28 x = (ll) x * 10 + ch - '0'; 29 ch = getchar(); 30 } 31 return sgn * x; 32 } 33 34 int main(){ 35 scanf("%d", &n); mod = read(); 36 for (int i = 1; i <= n; ++i){ 37 a = read(); 38 if (a < 0) a += (abs(a / mod) + 1) * mod; 39 s += a, s %= mod; 40 ans = max(ans, s); 41 if (S.upper_bound(s) != S.end()){ 42 p = *(S.upper_bound(s)); 43 ans = max(ans, (s + mod - p) % mod); 44 } 45 S.insert(s); 46 } 47 printf("%lld ", ans); 48 return 0; 49 }
(p.s. 无耻的我又用了set。。。)