【前缀和】B014_LQ_k倍区间(烂公式转换)

给定一个长度为N的数列,A1, A2, … AN,如果其中一段连续的子序列Ai, Ai+1, … Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。

你能求出数列中总共有多少个K倍区间吗?

输入
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
输出
输出一个整数,代表K倍区间的数目。

样例输入
5 2
1
2
3
4
5
样例输出
6
方法一:前缀和

s[i] 为子数组 A[0:i] 的前缀和,若有 (s[i]-s[j])%k=0,则有 s[i]%k-s[j]%k=0,也就是 s[i]%k=s[j]%k;

当枚举到 i 时,我们只需要在历史记录找到与 s[i]%k 相等的 s[j]%k(j

#include
using namespace std;
typedef long long ll;

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    ll n, k, ans=0; cin>>n>>k;
    ll A[n], s[n+1]={0}, cnt[n+1]; memset(cnt, 0, sizeof cnt);
    for (int i=0; i<n; i++) cin>>A[i], s[i+1]=(s[i]+A[i])%k;

    for (int i=1; i<=n; i++) {
        if (cnt[s[i]]>0) 
        	ans+=cnt[s[i]];
        cnt[s[i]]++;
    }
    cout << ans+cnt[s[0]];	//如果前缀和从
    return 0;   
}

复杂度分析

  • Time O ( n ) O(n) O(n)
  • Space O ( n ) O(n) O(n)

你可能感兴趣的:(#,前缀和与差分)