BZOJ3544 [ONTAK2010]Creative Accounting

看不懂题,就不能写的稍微像人话点吗我去。。。

题目就是要找一段区间使得Σ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 }
View Code

(p.s. 无耻的我又用了set。。。)

By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4044638.html