java k倍区间_AcWing 1230. K倍区间Java详细版

import java.io.;

import java.util.;

public class Main{

static Scanner cin = new Scanner(System.in);

static int N = cin.nextInt();

static int K = cin.nextInt();

static int[] s = new int[100010];

static int[] cnt = new int[100010];

public static void main(String args[]) throws Exception{

/*

三重循环得出答案(太暴力了,不可取!)

for(int r = 1; r <= n; r++){

for(int l = 1; l <= n; l++ ){

//双重循环枚举所有情况,例(按位置枚举):

第一次:1

第二次:1 2

2

第三次:1 2 3

2 3

3

int sum = 0;

for(int i = l; i <= r; i++){

sum += s[i]; //将枚举的所有数加起来

}

if(sum % k == 0){

cnt++; //cnt为答案

}

}

}

//此为累加,按以往的经验可变为前缀和;使用空间换时间的优化!(公式:s[i] = s[i - 1] + a[i])

修改:s[i] = s[i - 1] + cin.nextInt()

一并修改:s[i] = (s[i - 1] + cin.nextInt()) % K;以此达到了优化了两重循环

*/

for(int i = 1; i <= N; i++){

s[i] = (s[i - 1] + cin.nextInt()) % K;

}

long res = 0;

cnt[0] = 1; //当余数(此余数为该位置前缀和的余数)为0时,本身就可以成为一个K倍区间

for(int i = 1; i <= N; i++){

/*

当余数不唯0的时候,位置不同但是余数相同的两个位置组合一下可以成为一个K倍区间;

具体步骤为(每一个位置都为前缀和):后一个余数相同的位置-前一个余数相同的位置;

但编程中不需要考虑。

cnt[s[i]]是用来枚举余数是几的个数,第一次出现s[i];res += cnt[s[i]]是不会带来任何结果的,

cnt[s[i]] ++ 表示标记s[i]出现的个数,第一个出现的s[i]带来的结果是cnt[s[i]] ++ 等同于即cnt[s[i]] = 1,

之后依次累加,当第二次出现的时候,res += cnt[s[i]]等同于结果res += 1,再cnt[s[i]] ++,

表示余数的个数加1,为后面的继续使用;如果是cnt[0] = 1,默认res += cnt[s[i]]会+ 1;

再cnt[s[i]] ++,表示余数的个数加1,为后面的继续使用。

*/

res += cnt[s[i]];

cnt[s[i]]++;

}

System.out.println(res);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值