題目描述
給定乙個長度為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)
輸出 輸出乙個整數,代表ķ倍區間的數目。
樣例輸入
樣例輸出
學習過這道題讓自己非常深刻地體會到了自己對字首和知識的欠缺,天真的以為暴力就能解決一切
下次做題時一定要對連續區間要敏感,字首和是一種多麼方便的方法啊!!
看過網上各位大佬的題解之後,也對這個字首和還有取模又有了一種新的理解
比如 [ l , r ] 上的區間判斷其對k取模是否為0,用sum陣列儲存字首和,即 [ l ,r ]上的區間和就等於sum [ r ] - sum [ l-1]
而判斷sum [ r ] - sum [ l-1] 對k取模是否為0,就是判斷這兩個字首和對k取模是否相等
// 因為兩個數對k取餘後餘數相同,相減後 他們分別對k 取餘的餘數就減掉了
// 即(sum [ r ] - sum [ l-1] %k ==0 可以 推導出sum [ r ] %k==sum [ l-1 ]%k
而要實現上面說的這些步驟,就是對字首和取餘k
例如題目給的 1,2,3,4,5
取模2後的字首和分別是 1,1,0,0,1
其中 1 有三個 ,0 有兩個,對所有的1或所有的0中,根據組合數 c(3,2) 或c(2,2)求出其中的取模2後相同的字首和
**解釋:
//ans記錄的是 不從第乙個元素開始的區間的相同的個數,例如前面說的[2],[2,3,4,5],[3,4,5] (這些是取模2後為1的),[4](取模2後為0的)
//加上vis[0]是因為要記錄從從第乙個分別到第i個的區間中取模k 為 0的個數,例如([1,2,3],[1,2,3,4])
**如下
#includeint main()
; sum[1]=a[1]%k;
for(int i=2;i<=n;i++)
sum[i]=(sum[i-1]+a[i])%k;
long long vis[100007]=; // 該陣列是記錄有多少個相同的區間和
long long ans=0;
for(int i=1;i<=n;i++)
printf("%lld",ans+vis[0]);
//ans記錄的是 不從第乙個元素開始的區間的相同的個數
//加上vis[0]是因為要記錄從從第乙個分別到第i個的區間中取模k 為 0的個數
return 0;
}
藍橋杯 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 ...
藍橋杯 K倍區間
給定乙個長度為 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倍區間。你能求出數列中總共有多少個...