k倍区间 (抽屉原理)

转自:https://www.cnblogs.com/tyty-Somnuspoppy/p/8454521.html

给定一个长度为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
分析:
1、因为(sum[r] - sum[l-1]) % k == 0,可推出sum[r] % k == sum[l - 1] % k.
2、因此,将前缀和分别对K取模。
3、分别统计出取模后的各数字的个数。
#include<stdio.h>
using namespace std;
typedef long long LL;
const int MAXN = 100000 + 10;
int sum[MAXN];
int cnt[MAXN];
int main(){
	int N, K;
	scanf("%d%d", &N, &K);
	for (int i = 0; i < N; ++i){
		scanf("%d", &sum[i]);
	}
	sum[0] %= K;
	for (int i = 1; i < N; ++i){
		sum[i] = ((sum[i] % K) + sum[i - 1]) % K;
	}
	LL ans = 0;
	for (int i = 0; i < N; ++i){
		ans += cnt[sum[i]]++;
	}
	printf("%lld\n", ans + cnt[0]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37806112/article/details/79759516