Candy Distribution【K倍区间-蓝桥杯原题/取模+前缀和】

D - Candy Distribution

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≤l≤r≤N.

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

3 2

4 1 5

Sample Output 1

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

13 17

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

Sample Output 2

6

Sample Input 3

10 400000000

1000000000 1000000000 1000000000 1000000000 1000000000

1000000000 1000000000 1000000000 1000000000 1000000000

Sample Output 3

25


【感想】:

这个题就是蓝桥杯的原题叫作:K倍区间。

这个题就是对取模用处的最好的诠释了。

真的不错,可以对一个式子进行推导计算得到了。

【推导】:

题目给的N虽然是1e5,但是我们要枚举所有的区间,起码是N^2.

所以我们要思考一波。

首先我们知道表达一个区域『L,R』一定是用前缀和来处理对吧。

这个前缀和:sum[ R ]-sum[ L-1 ]。

我们想求一下K的倍数对吧。不就是对这个区域取模。

(Sum[ R ]- Sum[ L-1 ])%K==0;

但是我们知道,Sum[ R ]%K -Sum [ L - 1 ] %K==0 这个式子是等价对吧。

那么我们找的就是 (Sum[ L ]%K==0)或者(Sum[ R ] - Sum [ L-1 ])%K==0.

我们在任意一个   Sum【D】任意取两个作为两个端点就是,组合数:C_{n}^{2}

贴上代码给大家理解一下吧。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e6+10;
ll a[N],sum[N];
map<ll, int>mp;
int main()
{
    ll  n,k;
    scanf("%lld%lld",&n,&k);
    set<ll>S;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum[i]=(a[i]+sum[i-1])%k;
        mp[sum[i]]++;
        S.insert(sum[i]);
    }
    /*for(int i=1;i<=n;i++){
        printf("%d\n",sum[i]);
    }*/
    ll ans=mp[0];
    set<ll> ::iterator it=S.begin();
    for( ; it!=S.end();it++){
        int cur=*it;
        ll t=mp[cur];
        ans+=(t*(t-1))/2;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Z_sea/article/details/82054942