AcWing 1230. K倍区间 java 前缀和

给定一个长度为 N 的数列,A1,A2,…AN,如果其中一段连续的子序列 Ai,Ai+1,…Aj 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。

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

输入格式
第一行包含两个整数 N 和 K。

以下 N 行每行包含一个整数 Ai。

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

数据范围 ⭐ 10^5 -> O(nlogn) 或 O(n) ; long 类型 存数据

1≤N,K≤100000,

1≤Ai≤100000

输入样例:

5 2
1
2
3
4
5

输出样例:

6

⭐ 首先想一个暴力的做法(要求覆盖所有情况)

暴力:O(n^3)  ->   前缀和:O(n^2)
① 枚举区间的右端点
② 枚举特定右端点的所有左端点
③ 前缀和优化求区间和(暴力枚举求和也行)

⭐ 对暴力解法进行优化

O(n logn) 或 O(n)
① 对求解公式进行化简,发现只要 前缀和 的余数 相等 就是 k倍区间
② 开一个余数数组,下标是 余数数值,存的是 该余数数值 在 0~R 中出现了多少次

在这里插入图片描述

import java.io.*;
import java.util.*;

public class K倍区间
{
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
	static int N = (int) 1e5 + 10, n, k;
	static long[] s = new long[N];// 前缀和
	static long[] rm = new long[N];// 余数 remainder

	public static void main(String[] args) throws IOException
	{
		String[] a1 = in.readLine().split(" ");
		n = Integer.parseInt(a1[0]);
		k = Integer.parseInt(a1[1]);

		for (int i = 1; i <= n; i++)
		{
			long x = Long.parseLong(in.readLine());// 建议直接转换为 long 类型,以免造成精度损失
			s[i] = s[i - 1] + x;
		}

		long res = 0;
//s[0] = 0; 所以rm[0] = 0,因为求对 前缀和 求同余的数时用到 s[r] - s[l-1] ,s[l-1] ,
//而 l-1 有可能是 0,所以得事先初始化 rm[0] 为 1
		rm[0] = 1;
		for (int i = 1; i <= n; i++)
		{
			res += rm[(int) s[i] % k]; // 数组的下标是 int 类型(强转)
			rm[(int) s[i] % k]++;
		}

		System.out.println(res);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值