【蓝桥杯第八届B组省赛】k倍区间

【蓝桥杯第八届B组省赛】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

二、解法分析

1.同余定理

对于两个整数a,b,给定一个正整数d,若(a-b)%d=0,也就是(a-b)能够被d整除,那么我们就说a和b是模d同余的,记为a≡b(mod d)。
例如a=7,b=2,c=5。由于(7-2)%5==0,所以7和2是模5同余的。

2.本题的解法

我的解法是前缀和+同余定理,需要开一个余数数组sum,表示每个余数的数量。初始化余数数组,即sum[0]=1(0的数量设为1),其他余数数量均设为0。每计算完前i(1<=i<=n)个数的前缀和时,求出该前缀和模k得到的余数u,然后根据同余定理,在第i个数之前,模k后余数为u的前缀和个数=在第i个数之前的能够整除k的区间个数(区间包括第i个数),这个个数即为sum[u]。在遍历下个数之前,还需要更新余数数组,即sum[u]=sum[u]+1。

三、代码

代码比解法分析更清晰明了。

#include <bits/stdc++.h>
using namespace std;
long long sum[100009];//余数数组
long long sumed;
long long a[100009];
long long all;
int main()
{
    long long i;
    long long n;
    long long k;
    sum[0]=1;
    cin>>n;
    cin>>k;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
        sumed=sumed+a[i];
        long long u=sumed%k;
        all=all+sum[u];
        sum[u]++;
    }
    printf("%lld\n",all);
    return 0;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值