Atcoder contest 105 ABC D - Candy Distribution 前缀和 取模

D - Candy Distribution


Time limit : 2sec / Memory limit : 1024MB

Score : 400 points

Problem Statement

There are N boxes arranged in a row from left to right. The i-th box from the left contains Ai candies.

You will take out the candies from some consecutive boxes and distribute them evenly to M children.

Such being the case, find the number of the pairs (l,r) that satisfy the following:

  • l and r are both integers and satisfy 1≤lrN.
  • Al+Al+1+…+Ar is a multiple of M.

Constraints

  • All values in input are integers.
  • 1≤N≤105
  • 2≤M≤109
  • 1≤Ai≤109

Input

Input is given from Standard Input in the following format:

N M
A1 A2 … AN

Output

Print the number of the pairs (l,r) that satisfy the conditions.

Note that the number may not fit into a 32-bit integer type.


Sample Input 1

Copy

3 2
4 1 5

Sample Output 1

Copy

3

The sum Al+Al+1+…+Ar for each pair (l,r) is as follows:

  • Sum for (1,1): 4
  • Sum for (1,2): 5
  • Sum for (1,3): 10
  • Sum for (2,2): 1
  • Sum for (2,3): 6
  • Sum for (3,3): 5

Among these, three are multiples of 2.


Sample Input 2

Copy

13 17
29 7 5 7 9 51 7 13 8 55 42 9 81

Sample Output 2

Copy

6

Sample Input 3

Copy

10 400000000
1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

Sample Output 3

Copy

25 

 题意很简单,给你n个数,和一个m,问你存在多少个l到r区间,区间和可以整除m

 

整除,加区间和,自动想到了前缀和,然后再想,如果我们对所求前缀和modm,那么得到的就是所有的贡献,

现在来看这些贡献,2 0 2 0 2 0 2 0 2 0,这是第二组例子所得到的前缀和,那么当遇到2的时候,我们是知道

这个区间是不满足的,走到0的时候就开始满足了,说明1到2是可以整除m的,然后再到2,发现又是可以的,

因为对于2到3区间,他是满足的,我们之前出现过一次2,等到再出现2的时候,说明这个区间的前缀和是已经

满足了模m等于0的,我们就这样进行计数。

上面解释可能有点麻烦,我列个式子吧,

对于a到b区间,得到取模后的前缀和是x

对于a到c区间,得到取模后的前缀和是x

那么对于a到c区间里,肯定存在满足题意要求的区间,这个区间个数,就是每次遇到x的出现次数的求和,

 

 

代码如下:



#include <bits/stdc++.h>

using namespace std;

const int maxn = 200000;
map<long long,long long>mm;
int n;
long long m;
int main() {
    while(cin >> n >> m) {
        long long num,sum = 0,ans = 0;
        mm.clear();
        mm[0]++;
        for(int i = 1; i <= n; i++) {
            cin >> num;
            sum += num;
            sum %= m;
            ans += mm[sum];
            mm[sum]++;
//            cout << sum <<"   " << ans << endl;
        }
        cout << ans << endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值