0
点赞
收藏
分享

微信扫一扫

解析蓝桥杯思维之真题训练:k倍区间

cwq聖泉寒江2020 2022-03-24 阅读 61

目录

🍋题目描述

给定一个长度为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

🍋解题思路

🍊🍊思路一

暴力破解:
用s[i]存取前i项和。之后双指针,进行扫描。

不过这样运行超时了,练习系统中测得只有28分。

🍊🍊思路二

数学思维:
把前i项和s[i],进行对k的取余,对取余结果相等的任两个前n项和都能是k倍区间

🍋源代码

🍊🍊思路一代码

import java.util.Scanner;

public class Main
{
	static int n,k;
	static int[]a;
	static int[]s;
	
	public static void main(String[] args){
		Scanner in=new Scanner(System.in);//输入的前提语句
		n=in.nextInt();//输入多少个数字
		k=in.nextInt();//输入k
		a=new int[n+1];//java的特性,充分利用空间
		s=new int[n+1];
		s[0]=0;//因为我们输入是从1开始的
		for(int i=1;i<=n;i++) {
			a[i]=in.nextInt();
			s[i]=s[i-1]+a[i];//得到前i项和,即前缀和
		}
		
		long ans=0;
		//枚举i,j
		for(int i=1;i<=n;i++) {
			for(int j=i;j<=n;j++) {
				//ij之间的区间和=s[j]-s[i-1]
				if((s[j]-s[i-1])%k==0) {
					ans++;
				}
			}
		}
		System.out.println(ans);
	}
}

🍊🍊思路二代码

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main
{
	static int n,k;
	static int[]a;
	static int[]s;
	static Map<Integer,Long> cnt=new HashMap<Integer,Long>();//同余的个数统计
	
	public static void main(String[] args){
		Scanner in=new Scanner(System.in);//输入的前提语句
		n=in.nextInt();//输入多少个数字
		k=in.nextInt();//输入k
		a=new int[n+1];//java的特性,充分利用空间
		s=new int[n+1];
		s[0]=0;//因为我们输入是从1开始的
		cnt.put(0,1l);//1l就是为long型的1
		for(int i=1;i<=n;i++) {
			a[i]=in.nextInt();
			s[i]=(s[i-1]+a[i])%k;//得到前i项和对k的余数,即前缀和的余数
			if(cnt.get(s[i])==null) {
				cnt.put(s[i], 1l);
			}
			else {
				cnt.put(s[i], cnt.get(s[i])+1);
			}
		}
		
		long ans=0;
		for(int i=0;i<k;i++) {//余数必然在0~k-1之间
			Long cntI=cnt.get(i);
			if(cntI==null) cntI=0l;
			ans+=cntI*(cntI-1)/2;//例如所有前缀和中%k=3的有3个,那么他们任意选2可得一个k倍区间,c32
			
		}
		System.out.println(ans);
	}
}

🍋其他真题

链接: 最全的2021蓝桥杯算法课《算法很美》的学习笔记总目录+真题详解.
在这里插入图片描述

举报

相关推荐

0 条评论