藍橋杯-k倍區間

小程xy發表於2024-05-03

給定一個長度為 N 的數列,A1,A2,…AN,如果其中一段連續的子序列 Ai,Ai+1,…Aj 之和是 K 的倍數,我們就稱這個區間 [i,j] 是 K 倍區間。

你能求出數列中總共有多少個 K 倍區間嗎?

輸入格式

第一行包含兩個整數 N 和 K。

以下 N 行每行包含一個整數 Ai。

輸出格式

輸出一個整數,代表 K 倍區間的數目。

資料範圍

1≤N,K≤100000,1≤Ai≤100000

輸入樣例:

5 2
1
2
3
4
5
輸出樣例:
6

題解:

  • 先求字首和
  • 對字首和s[i] 取餘, 餘數相同的字首和 互相相減是 k 的倍數 (ps : 如果餘數相同的個數是4, 那麼 答案應該加上 3 + 2 + 1; 相同的個數是 3 的話, 應該加上 2 + 1, 還不懂的話看下圖)
  • 區間中只有一個元素的也符合題意

下圖模擬的是樣例

#include <bits/stdc++.h>
#define int long long    // 會爆 int
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N];
signed main()
{
    int n, k; cin >> n >> k;
    int sum = 0;
    for (int i = 1; i <= n; i ++) 
    {
        cin >> a[i]; a[i] += a[i - 1];    // 求字首和
    }
    for (int i = 1; i <= n; i ++)
    {                        // 👇 圖解 
        if (b[a[i] % k] != 0) sum += b[a[i] % k];  
        b[a[i] % k] ++;
    }
    cout << sum + b[0] << endl; // 餘數是0的代表自己是一個區間, 符合題意, 所有 最終答案要加上b[0]
    return 0;
}

覺得寫的不錯的話, 點個贊吧~