区间处理 之 取模 (前缀和) [AtCoder - 4240] Candy Distribution

 https://vjudge.net/problem/AtCoder-4240

题意: 求所有区间中能够被 m 整除的有几个?

思路:根据同余定理,(a-b)%m=a%m-b%m, 显然要用到前缀和

分析:用 前缀和 处理区间问题,并且利用取模的特殊性质:如果余数相等,那么两个数相减就是整除的数,这刚好和前缀和的求区间和对应上了。

注意:不可能用数组来记录1E9种余数,所以要用 map ,一共只有1e5个数,最多只有1e5个值,用map把余数和个数对应起来。

且当位置i的前缀和可以被m除尽时,是可以以第一项为起点的。这种情况会被忽略,所以要在结果中补上。

#include <bits/stdc++.h>
using namespace std;

map<long long ,long long> mp;
const int maxn = 2e5;

int n,m;
long long a[maxn];
long long pre[maxn];
long long cnt[maxn];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        cin>>a[i];
        pre[i] = pre[i-1]+a[i];
    }
    long long ans=0;
    for(int i=1; i<=n; i++){
        ans += mp[pre[i]%m];
        //cout<<pre[i]%m<<endl;
        //ans += cnt[ pre[i]%m ];
        if( pre[i]%m==0 )
            ans++;
        mp[ pre[i]%m ]++;
        //cnt[ pre[i]%m ]++;
    }
    cout<<ans<<endl;

}

猜你喜欢

转载自www.cnblogs.com/-Zzz-/p/11735370.html