K倍區間 第八屆藍橋杯省賽C B組

2021-10-10 00:08:14 字數 1987 閱讀 1289

題目描述:

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

345輸出樣例:

解題思路:

1.最簡單的方法,採用暴力列舉,三層迴圈

for

(int r =

1; r <= n; r++

)for

(int l =

1; l <= n; l++

) 判斷是否可整除k

}

這個方法最簡單,最容易想到,但是時間複雜度在 n 的三次方,因為資料量是100000,所以肯定不過。

2.公升級版1

優化最裡面一層迴圈,將其優化,可以另外開闢乙個陣列sum,存前n項和,這樣,裡面可以變成

sum[r]-sum[l-1]

for

(int r =

1; r <= n; r++

)for

(int l =

1; l <= n; l++

)}

這樣子,較為容易想到,時間複雜度在n的二次方,資料量太大,依舊過不掉,因為在十萬次,所以平方次複雜度仍過高

3.極度優化

因為:(sum[r]-sum[l])%k==0)

所以:只要sum[r]%k == sum[l]%k,則這個區間是k被區間,也就是說,只要兩個模k的餘數相同,即兩數區間為k倍區間,所以,可以開闢陣列,存餘數相同的個數

ac**:

#include

using

namespace std;

long

long sum[

100005];

//存放字首和

long

long re[

100005];

//存放模k的餘數

intmain()

long

long res =0;

//res存放幾個k倍區間

re[0]

=1;//我們的sum[0]預設是0,所以re[0] = 1,這裡可能很多人不能理解,因為當餘數是0的時候,其實那乙個數字也可以的,

/* 例如,樣例輸入

5 21 2 3 4 5

這時候 sum陣列是: 1 3 6 10 15

取模的時候是:1 1 0 0 1

但是這個時候注意:當餘數0這個數字剛放進去的時候,切記,這個數字也是單個其實就是k的倍數了,所以這個re[0] = 1,為的就是把這個單個數字計算進去,

可能會有人說,那如果餘數為0的,是不是多算了

你們可以試試

例如:1 2

1這個時候sum是:1

取模是:1

那麼計算的時候在下面迴圈的時候不會有re[0]加進去

這就是為什麼re[0]=1;

*/for(

int i =

1; i <= n; i++

)printf

("%lld"

, res)

;//最後輸出結果,ac

return0;

}

第八屆藍橋杯省賽C B組 K倍區間

給定乙個長度為 n 的數列,a1,a2,an,如果其中一段連續的子串行 ai,ai 1,aj 之和是 k 的倍數,我們就稱這個區間 i,j 是 k 倍區間。你能求出數列中總共有多少個 k 倍區間嗎?輸入格式 第一行包含兩個整數 n 和 k。以下 n 行每行包含乙個整數 ai。輸出格式 輸出乙個整數,...

第八屆藍橋杯省賽C B組 K倍區間

演算法標籤 字首和 題目描述 給定乙個長度為 n 的數列,a1,a2,an,如果其中一段連續的子串行 ai,ai 1,aj 之和是 k 的倍數,我們就稱這個區間 i,j 是 k 倍區間。你能求出數列中總共有多少個 k 倍區間嗎?輸入格式 第一行包含兩個整數 n 和 k。以下 n 行每行包含乙個整數 ...

第八屆藍橋杯C B組 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 ...