zl程序教程

您现在的位置是:首页 >  后端

当前栏目

蓝桥杯 历届试题 K倍区间数(C语言)

C语言试题 蓝桥 区间 历届
2023-06-13 09:13:12 时间

K倍区间数 问题描述    给定一个长度为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 数据规模和约定

思路:要求的是k的区间 而且是任意起点都可以,也就是随便截取区间只要是K的倍数即可。 那这里我们肯定得做取余运算了,如果余数为0当然是k的倍数了 那么余数不为0就不是K的倍数, 但是 仔细想一想 两个区间对k的取余结果相同,比如余数都为1时,此时这两个区间相减之后的 区间就是K的倍数了,但然这里不用担心,因为每次取到的都是连续的区间,所以减出来的区间也是连续的。 这里用到了sum来存余数x对应这个有y个区间,对于每种不同的区间他们的数量就是C(n,2), 就是n个里取两个相减,当然这里有特殊,就是余数为0的情况需要额外加1 因为 比如说S5就是K的倍数,他不需要减什么区间,但是在我们的运算中是要取到两个区间,所以要额外加1 相当于加了个 和为0的区间S0

#include <stdio.h>
int main()
{
  long int i,n,k,j,s,s1;
  long long sum[100001],js[100001]={0};
  sum[0]=0;long long ans=0;
  scanf("%ld%ld",&n,&k);
  for(i=1;i<=n;i++)scanf("%ld",&s),sum[i]=sum[i-1]+s; 
   js[0]=1;
    for(j=1;j<=n;j++)js[sum[j]%k]++;
    for(i=0;i<k;i++)if(js[i])ans+=(js[i]*(js[i]-1))/2;//C(n,2) 从 众多区间里选两个 都可构成 
printf("%lld\n",ans); 
return 0;
}