P8649 [蓝桥杯 2017 省 B] k 倍区间(java)

题目描述

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

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

输入格式

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

以下 NN 行每行包含一个整数 AiAi​(1≤Ai≤105)(1≤Ai​≤105)。

输出格式

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

输入输出样例

输入 

5 2
1  
2  
3  
4  
5  

输出

6

说明/提示

时限 2 秒, 256M。蓝桥杯 2017 年第八届

 传统暴力肯定会超时,所以用同余定理优化了

同余定理:如果a%c=b%c,那么(a+b)%c=0,(a-b)%c=0

例如:如果两个区间同余就说明这两个区间多了一个K倍区间,1 2 3 4 5 6可以看做:

            0 1 2 3  4   5

sum     0 1 3 6 10 15

arr[]数组记录的是同余区间个数,比如如果f[0]=2,再出现一个区间和%k==0的话,sum1=sum1+1*2,因为f[0]里面有两个%k=0的区间,再出现的区间分别与各区间之中多了一个k区间。

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        final Scanner scan = new Scanner(System.in);
        int N=scan.nextInt();
        int k=scan.nextInt();
        int[] arr=new int[k];
        long sum=0,sum1=0;
        arr[0]=1;
        for(int i=0;i<N;i++){
            sum=sum+scan.nextLong();
            sum1=sum1+arr[(int)(sum%k)];
            arr[(int)(sum%k)]++;
        }
        System.out.println(sum1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值