【蓝桥杯 - 练习】k倍区间(思维,数组)
題干:
http://lx.lanqiao.cn/problem.page?gpid=T444
問題描述
給定一個(gè)長度為N的數(shù)列,A1, A2, ... AN,如果其中一段連續(xù)的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍數(shù),我們就稱這個(gè)區(qū)間[i, j]是K倍區(qū)間。
你能求出數(shù)列中總共有多少個(gè)K倍區(qū)間嗎?
輸入格式
第一行包含兩個(gè)整數(shù)N和K。(1 <= N, K <= 100000)
以下N行每行包含一個(gè)整數(shù)Ai。(1 <= Ai <= 100000)
輸出格式
輸出一個(gè)整數(shù),代表K倍區(qū)間的數(shù)目。
樣例輸入
5 2
1
2
3
4
5
樣例輸出
6
?
解題報(bào)告:
? ? 首先看到連續(xù)區(qū)間想到前綴和,看到數(shù)據(jù)范圍想想,可否滿足某個(gè)遞推關(guān)系,即:知道了某一個(gè)區(qū)間是k倍區(qū)間,相應(yīng)的可以推出另外的區(qū)間也是k倍區(qū)間。或者,預(yù)處理出某些值,方便得到我們想要的結(jié)果。
? ? 可以想出,mod k? 同余的兩段區(qū)間合并起來肯定是%k==0的,所以我們預(yù)處理出前綴和的余數(shù)。代碼就不難寫了。
AC代碼:(大一的代碼了、、、懷念逝去的時(shí)光啊!順便吐槽一下當(dāng)時(shí)寫代碼的稚嫩)
#include<iostream> using namespace std; int yu[1000005]; int a[1000005]; int main() {int n,k;long long int cnt=0;//用int有一個(gè)案例過不了 scanf("%d%d",&n,&k);for(int i=1;i<=n;i++){scanf("%d",&a[i]);a[i]=(a[i]+a[i-1])%k; //一般的前綴和 a數(shù)組 要開longlong,因?yàn)樗抢奂拥暮桶?#xff01;可能很大呢!這也給我們個(gè)提示,需要在這里同時(shí)進(jìn)行求余 yu[a[i]]++; //這也是為什么i從1開始而不從0開始的原因、 }for(int i=0;i<k;i++){//cnt+=( yu[i] * (yu[i]-1))/2; //cnt+=(yu[i]*yu[i-1])/2;cnt+=( (yu[i]/2.0) * ( (yu[i]-1)/2.0 ))*2; //cnt+=( (yu[i]/2) * ( (yu[i]-1)/2 ))*2; }cnt+=yu[0];printf("%lld",cnt);return 0 ; } //5 2 //1 //2 //3 //4 //5AC代碼2:(標(biāo)解)
#include<iostream> using namespace std; typedef long long ll; ll bk[100010] = {0}; ll arr[1000010]; int main() { int n,k;scanf("%d%d",&n,&k);for(int i = 0; i < n; i++)scanf("%lld",&arr[i]);arr[0] %= k;ll sum = 0;for(int i = 1; i < n; i++)arr[i] = (arr[i]+arr[i-1])%k;for(int i = 0; i < n; i++)sum += (bk[ arr[i] ]++);printf("%lld",sum+bk[0]);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的【蓝桥杯 - 练习】k倍区间(思维,数组)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新能源还会有上涨的行情吗?新能源是长期的
- 下一篇: 【HDU - 5688 】Problem