2021.01.26k倍区间

本文介绍了一种高效计算K倍区间数量的方法。利用前缀和的概念,文章提出了一种组合数学公式,避免了双重循环的低效遍历,显著提高了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021.01.26k倍区间

题目描述

给定一个长度为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. 前缀和
  2. 如果两个前缀和A(对应下标i),B(对应下标j),有A%k == B%k,则 [ i+1,j ] 中的元素一定是一个k倍区间。

注意:为了性能,在找k倍区间个数的时候,采取组合数学的式子num = n*(n-1)/2,即计算,而不是通过两个for循环进行遍历。

代码

    class Solution {
        int n,k;
        void test() {
            Scanner cin = new Scanner(System.in);
            n = cin.nextInt();
            k = cin.nextInt();
            int[] a = new int[n+1];a[0] = 0;int s = 0;
            int[] num = new int[k];
            for(int i = 1; i <= n; i++) {
                int t = cin.nextInt();
                s+=t;
                s= s%k;
                a[i] = s;
            }
            for(int i = 0; i < n+1; i++) {
                num[a[i]]++;
            }
            long cnt = 0;
            for(int i = 0; i < k; i++) {
                if(num[i] != 0) {
                    cnt+=(long)num[i]*(long)(num[i]-1)/2;
                }
            }
            System.out.println(cnt);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值