歷屆試題 k倍區間

2021-09-11 22:26:16 字數 1727 閱讀 1161

問題描述

給定乙個長度為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 2123

45樣例輸出

資料規模和約定

峰值記憶體消耗(含虛擬機器) < 256m

cpu消耗 < 2000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:「請您輸入...」 的多餘內容。

注意:main函式需要返回0;

只使用ansi c/ansi c++ 標準;

不要呼叫依賴於編譯環境或作業系統的特殊函式。

所有依賴的函式必須明確地在原始檔中 #include

不能通過工程設定而省略常用標頭檔案。

提交程式時,注意選擇所期望的語言型別和編譯器型別。

思路:

通過字首和的方式,計算sum【i】mod   k 的值,i++,等到下乙個相等時,ans+=cnt【sum【i】 】

求區間[l,r]的和是k的倍數的個數。求區間和,我們可以通過字首和來求出。我們規定sum[i]表示第1個元素到第i個元素的和。那麼sum[r] - sum[l-1]就是區間[l,r]的和。區間[l,r]的和是k的倍數即(sum[r] - sum[l-1])%k == 0 即sum[r]%k == sum[l-1]%k

那麼,我們求出每個字首和,在求的過程中取模,兩個相等的字首和就能組成乙個k倍區間。我們可以在計算完字首和以後,使用兩層for迴圈來計數k倍區間的個數。但是由於資料量較大,這樣是會超時的。那麼我們是否能在計算字首和的過程中來記錄k倍區間的個數呢?

我們用乙個陣列cnt[i]表示當前位置之前,字首和取模後等於i的個數。舉個例子:

數列 1 2 3 4 5   mod = 2

對前1個數的和取模, 為1 之前有0個字首和取模後為1,個數+0

對前2個數的和取模, 為1 之前有1個字首和取模後為1,個數+1

對前3個數的和取模, 為0 之前有0個字首和取模後為0, 個數+0

對前4個數的和取模, 為0 之前有1個字首和取模後為0,個數+1

對錢5個數的和取模, 為1 之前有2個字首和取模後為1,個數+2

到目前為止ans = 4。但是ans應該等於6,因為這樣計算後,我們漏掉了前i個數的和取模是k的倍數的情況,即[0,i]區間和是k的倍數,因此,我們要在ans = 4 的基礎上 加上字首和取模後為0的個數 即ans+2 = 6;

**如下:

#include using namespace std;

#define m 100005

int sum[m];

int cnt[m];

long long int ans;

int main()

printf("%lld\n",ans+cnt[0]);

return 0;

}

題目思路來自以下部落格:

歷屆試題 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 ...

歷屆試題 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 ...

歷屆試題 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 ...