AC1230 k倍區間(藍橋杯)

2021-10-19 08:08:32 字數 2170 閱讀 8569

題意:問有多少段的和能被k整除

這個題跟我入隊考試的題非常的像。

首先他問我們某一段的和是不是乙個k的倍數,那麼一段和我們很自然的就聯想到字首和了。而且我們知道,如果對每乙個字首和都進行%k處理,那麼就一定會使得某些數是0(假設這個數的位置是i),那麼就說明從1到i的所有的數的和都是k的倍數。那麼我們也會得到有的和並不是0,而是1~(k - 1)中的數。但是不妨礙裡面有相同的數。

假設 s[i] % k = x,那麼我們有取餘的定義可知:

s [i

]/k=

n⋯xk

∗n+x

=s[i

]s[i] / k = n \cdots x \\ k * n + x = s[i]

s[i]/k

=n⋯x

k∗n+

x=s[

i]那麼假設還有乙個數s[j]的取餘結果也是x,同理

k ∗m

+x=s

[j

]k * m + x = s[j]

k∗m+x=

s[j]

兩式相減得:

k ∗n

−k∗m

=s[i

]−s[

j]k∗

(n−m

)=s[

i]−s

[j

]k*n - k*m=s[i]-s[j]\\ k*(n-m) = s[i]-s[j]

k∗n−k∗

m=s[

i]−s

[j]k

∗(n−

m)=s

[i]−

s[j]

那麼就可以得到:

( s[

i]−s

[j])

/k=(

n−m)

⋯0

(s[i]-s[j]) / k = (n - m) \cdots 0

(s[i]−

s[j]

)/k=

(n−m

)⋯0即:

( s[

i]−s

[j])

%k=0

(s[i]-s[j]) \% k = 0

(s[i]−

s[j]

)%k=

0那麼我們就能得到一下結論:

如果某個餘數在出現過之後在它後面再次出現過,那麼 [ i , j ]這個區間就可以是個k倍區間。

所以說,假設乙個餘數出現過 m 次,那麼同時包含這個餘數的k倍區間的個數就是 (m - 1) * m / 2次(因為出現的第一次無法與前面組成k倍區間)

假設出現了5次

1 2 3 4 5

1 21 3

2 31 4

2 43 4

1 52 5

3 54 5

每個位置與前面的組成答案,就是 1 + 2 + 3 + 4 + …(n - 2) * (n -1) = (n - 1) * n / 2

當0為餘數的時候,就是它出現的次數就是(m + 1) * m / 2(餘數是0 的時候,第一次出現的那個位置也可以組成乙個k倍區間)

#include

#include

#define ll long long

using

namespace std;

int n;

ll a[

100000+10

];int k;

ll s[

100000+10

];//看資料範圍我們知道,a[i]最大100000,你們到最後s[i]最大到100000 * 100000 = 10^10超出int

vector wei[

100000+10

];//存第幾位出現的,其實這裡只存出現的個數就行;讀者可以自行更改一下

intmain()

ll x = wei[0]

.size()

; ll cnt = x *

(x +1)

/2;for

(int i =

1; i <= k; i++

) cout << cnt;

return0;

}

其實這種做法跟y總的思路差不多,

藍橋杯 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...

藍橋杯 K倍區間

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

藍橋杯 k倍區間

暴力模擬 雙迴圈肯定超時了,需要找到數字間的規律進行優化 includeusing namespace std typedef long long ll define maxn 100005 sum r sum l 1 就是區間 l,r 的和。區間 l,r 的和是k的倍數即 sum r sum l ...