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。。。)

转载于:https://www.cnblogs.com/rausen/p/4044638.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值