蓝桥杯 17省赛 B10 K倍区间(dp)

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

输入

第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)

输出

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

例如,
输入:
5 2
1
2
3
4
5

程序应该输出:
6

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

===========

思路:
双层嵌套for,控制移动指针bgn,end->任意读取一段输入

{全集=(i)+(i +1) +…(i +k)}

,这里的全集由双层for的结构得出,判断是否为k倍区间->复杂=O(n^2)->输入规模较大时->超时×
为使复杂度为O(n)->减少一层for的枚举->减少一个移动指针,将起点指针固定在头部,移动终点指针,多声明一个数组空间保存每一次输入后的前缀和的对于k的模(两端数据的起点相同,对K值取得的模也相同,说明两者差值恰为k区间)->此时

{全集=为K区间的第i项前缀和的个数+为K区间的第i项前缀和与之前前缀和的差值}

来一波ppt作图
在这里插入图片描述

public class k倍区间 {
	static int[] sum =new int[100001];			//前i项和
	static int[] cnt =new int[100001];			//前缀和的模的出现次数(count简写)
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n =sc.nextInt();
		int k =sc.nextInt();
		long ans =0L;
		int tmp_numb =0;
		for(int i =1 ;i <=n ;i ++) {
			tmp_numb =sc.nextInt();				//第i项输入
			sum[i] =(sum[i -1] +tmp_numb) %k;	//第i项前缀和的模
			ans +=cnt[sum[i]];					//第i项之前模的出现次数->存在几段差值恰为k倍的区间
			cnt[sum[i]] ++;						//累加前缀和的模的出现次数
		}
		sc.close();
		System.out.println(ans +cnt[0]);		//输出全集=前缀和为K区间的个数+前缀和差值为k区间的个数
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肯尼思布赖恩埃德蒙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值