k倍区间

本文最后更新于:35 分钟前

[蓝桥杯 2017 省 B] k 倍区间

题目描述

给定一个长度为 N 的数列,A1,A2,A3,…AN,如果其中一段连续的子序列Ai,Ai+1,…Aj(ij) 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。

你能求出数列中总共有多少个 K 倍区间吗?

输入格式

第一行包含两个整数 NK(1≤N,K≤105)。

以下 N 行每行包含一个整数Ai*(1≤Ai*≤105)。

输出格式

输出一个整数,代表 K 倍区间的数目。

样例 #1

样例输入 #1

1
2
3
4
5
6
5 2
1
2
3
4
5

样例输出 #1

1
6

理解

记录一下前缀和,再用一个cnt来记录每个前缀和的余数的个数,两个余数相等的相减为0,0本来就满足,所以初始化时,cnt[0]=1;

代码

两重循环

过了40分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include<cstdio>
#include <sstream>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
int n,k;
const int N=1e5+1e4;
int arr[N];
long long sum[N];
int main()
{

cin>>n>>k;
for(int i=1;i<=n;i++)
{
scanf("%d",&arr[i]);
sum[i]=sum[i-1]+arr[i];
}
long long res=0;
for(int i=0;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if((sum[j]-sum[i])%k==0)res++;
}
}
cout<<res<<endl;
return 0;
}

满分 这里用余数的概念,任意两个余数相减等于0;

只用一层for循环即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include<cstdio>
#include <sstream>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
int n,k;
const int N=1e5+1e4;
int arr[N];
long long sum[N];
int cnt[N];
int main()
{

cin>>n>>k;
for(int i=1;i<=n;i++)
{
scanf("%d",&arr[i]);
sum[i]=sum[i-1]+arr[i];
}
long long res=0;
cnt[0]=1;
for(int i=1;i<=n;i++)
{
res+=cnt[sum[i]%k];
cnt[sum[i]%k]++;
}
cout<<res<<endl;
return 0;
}


k倍区间
http://example.com/2023/04/24/K倍区间/
作者
zzh
发布于
2023年4月24日
更新于
2023年4月24日
许可协议
原文链接: HTTPS://ZHANGZHIHAO-BLOG.GITHUB.IO
版权声明: 转载请注明出处!