首页 > 代码库 > BZOJ3544 [ONTAK2010]Creative Accounting

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\n", ans);48     return 0;49 }
View Code

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

BZOJ3544 [ONTAK2010]Creative Accounting