給定乙個長度為 n
nn 的數列,a1,
a2,…
an
a_1,a_2,…a_n
a1,a2
,…a
n,如果其中一段連續的子串行 ai,
ai+1
,…aj
a_i,a_,…a_j
ai,ai
+1,
…aj
之和是 k
kk 的倍數,我們就稱這個區間 [i,
j]
[i,j]
[i,j
] 是 k
kk倍區間。
你能求出數列中總共有多少個 k
kk 倍區間嗎?
輸入格式
第一行包含兩個整數 n
nn 和 kkk
以下 n
nn 行每行包含乙個整數 a
ia_i
ai。
輸出格式
輸出乙個整數,代表 k
kk 倍區間的數目。
資料範圍
1 ≤n
,k
≤100000
1≤n,k≤100000
1≤n,k≤
1000
00,1≤a
i≤
100000
1≤a_i≤100000
1≤ai≤
1000
00輸入樣例1:
5 212
345
輸出樣例1:6
按照樸素的做法,我們需要列舉區間端點,這個的複雜度是o(n
2)
o(n^2)
o(n2
)。然後再用o(n
)o(n)
o(n)
的複雜度求出區間的總和,看看其是否是k
kk的倍數。此時必定超時。
可以看出,求區間總和我們可以利用字首和將複雜度降到o(1
)o(1)
o(1)
,那麼總的複雜度就會降到o(n
2)
o(n^2)
o(n2
),但是仍然會超時,所以我們需要想更優化的方案
我們在列舉左端點的時候,其實可以先列舉右端點,(s[r] - s[l - 1]) % k == 0
,所以如果對於0 ~ r - 1
,我們只需要知道s[l]與 s[r]
模k同餘的個數,所以我們可以利用cnt
陣列來記錄每乙個r % k
的值,然後對於列舉每一r
,結果加上cnt[s[r] % k]
的個數即可
時間複雜度
o (n
)o(n)
o(n)
c++ **
#include
using namespace std;
typedef
long
long ll;
const
int n =
100010
;ll cnt[n]
, s[n]
;int n, k;
intmain()
ll res =0;
cnt[0]
++;// s[0] = 0,0 % k = 0;
for(
int r =
1;r <= n;r ++
)
cout << res << endl;
return0;
}
藍橋杯 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 ...