2017藍橋杯 k倍區間 字首和

2021-07-30 06:34:11 字數 1832 閱讀 3103

給定乙個長度為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資源約定:

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

cpu消耗 < 2000ms

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

注意:

main函式需要返回0;

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

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

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

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

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

分析;

不知道為什麼是最後一題 我的時間複雜度可能太高了

#include 

using namespace std;

int main()

intcount = 0;

for(int i = 0; i < n; i++)

}

}

cout

0; }

改後:

**大佬:

通過字首和的方法,把o(n方)的複雜度降低到了o(n),雖然學了挺久,看了挺久,但也算是學會了

主要思想:是使要加和的資料完全儲存,並且在下一次計算中直接呼叫,線性遞推.

分析:

統計字首和

sum[1] = a1;

sum[2] = a1+a2;

sum[i] = a1+a2+…+ai;

對於任意一段區間[l,r]的和就是sum[r]-sum[l-1].

(sum[r]-sum[l-1])%k 保證了[l,r]這段區間要麼%k等於0 要麼比k小 等於0這表示了正好是k的倍數 然後通過字首和相同的資料來判斷出剩下的k的倍數:(sum[r]-sum[l-1])%k == 0.變形後就是:sum[r]%k==sum[l-1]%k .

程式分析樣例:

輸入: 1 2 3 4 5

%k後字首和: 1 1 0 0 1

當i = 0, sum=0,bk[1]=1;

當i = 1, sum=1,bk[1]=2; //因為當bk[1]之前為1時 可得相減=0為k的倍數

當i = 2, sum=1,bk[0]=1;

當i = 3, sum=2,bk[0]=2; //同上理,當0-0時還是0

當i = 4, sum=4,bk[1]=3; //之前bk[1]有2個 所以有2種-法 所以sum加上2

最後統計bk[0]有幾個 sum+=bk[0] //因為之前只考慮了相減的情況 沒有考慮到本身

sum = 6;

#include 

using

namespace

std;

typedef

long

long ll;

ll bk[100010] = ;

ll arr[1000010];

int main()

藍橋杯2017初賽 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 100...

藍橋杯2017初賽 k倍區間 (字首和)

已知a那麼我們就可以將字首和模k的值為0,1,2 k 1的區間數分別求出來,然後分別計算。例如字首和模k為1的區間有x個。那麼就可以產生c x,2 個k倍區間 即x x 1 2個 然後對0 k 1分別進行此操作並求和。此題的關鍵是要知道 當兩個數的餘數相同時,這兩個數的差的餘數為0!include ...

藍橋杯2017初賽 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 10...