C語言實現 藍橋杯 歷屆試題 k倍區間

試題 歷屆試題 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)
  以下N行每行包含一個整數Ai。(1 <= Ai <= 100000)


輸出格式

       輸出一個整數,代表K倍區間的數目。


樣例輸入

5 2
1
2
3
4
5

樣例輸出

6

數據規模與約定

峯值內存消耗(含虛擬機) < 256M
CPU消耗 < 2000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
注意:
 main函數需要返回0;
 只使用ANSI C/ANSI C++ 標準;
 不要調用依賴於編譯環境或操作系統的特殊函數。
 所有依賴的函數必須明確地在源文件中 #include <xxx>
 不能通過工程設置而省略常用頭文件。
 提交程序時,注意選擇所期望的語言類型和編譯器類型。

試題分析

k倍區間指Ai,Ai+1,…Aj(i≤j)之和是k的倍數的區間即數列An的[Ai,Aj]範圍內子數列的和爲k的倍數的子數列。那麼可設該和爲sumij,前i項和爲sumi,前j項和爲sumj,且由已知可得sumij=sumj-sumi
那麼k倍區間就是①sumij%k=0,即(sumj-sumi)%k=0,即sumj%k-sumi%k=0即②sumi%k=sumj%k;到這裏題目也就轉化成對∀i,j∈[1,n]求滿足①或②條件的子數列的個數。這樣先求條件滿足條件②的個數就可以大大的減少計算量

代碼

#include<stdio.h>
int main(){
	int n,k;
	scanf("%d%d",&n,&k);
	int a[n+1],sum[n+1],b[100000]={0},i;
	long long ans=0;//ans統計k倍區間的個數 
	sum[0]=0;//這裏需要初始化一下sum[0] 
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
		sum[i]=(sum[i-1]+a[i])%k;//sum爲前i個數對k取餘後的值 
		ans+=b[sum[i]];//b[sum[i]]代表目前值爲sum[i]的個數,ans代表滿足條件②的個數
		b[sum[i]]++;//對值爲sum[i]的個數+1 
	}
	printf("%I64d",ans+b[0]);//b[0]代表滿足條件①的個數
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章