[蓝桥杯 2017 省 B] k 倍区间

题目链接

[蓝桥杯 2017 省 B] k 倍区间

题目描述

给定一个长度为 N N N 的数列, A 1 , A 2 , A 3 , . . , A N A_1,A_2,A_3,..,A_N A1,A2,A3,..,AN,如果其中一段连续的子序列 A i , A i + 1 , . . . , A j A_i,A_{i+1},...,A_j Ai,Ai+1,...,Aj 之和是 K K K 的倍数,我们就称这个区间 [ i , j ] [i,j] [i,j] 是 K K K倍区间。

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

输入格式

第一行包含两个整数 N N N 和 K K K。

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

输出格式

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

输入输出样例
输入

5 2

1

2

3

4

5

输出

6

数据范围
  • 1 ≤ N , K ≤ 1 0 5 1 \leq N,K \leq 10^5 1≤N,K≤105
  • 1 ≤ A i ≤ 1 0 5 1 \leq A_i \leq 10^5 1≤Ai≤105

解法:前缀和 + 哈希表

我们用 s s s 表示 数列 a a a 的前 n n n 项和:

  • s [ 0 ] = 0 s[0] = 0 s[0]=0
  • s [ 1 ] = a [ 1 ] + 0 s[1] = a[1] + 0 s[1]=a[1]+0
  • s [ 2 ] = a [ 2 ] + a [ 1 ] + 0 s[2] = a[2] + a[1] + 0 s[2]=a[2]+a[1]+0
  • ...

如果区间 [ i , j ] [i,j] [i,j] 是一个 K K K倍区间,那么显然 [ i , j ] [i,j] [i,j] 的区间和 s [ j ] − s [ i − 1 ] s[j] - s[i - 1] s[j]−s[i−1]是 K K K 的倍数,也就是 ( s [ j ] − s [ i − 1 ] ) % K = 0 (s[j] - s[i -1]) \% K = 0 (s[j]−s[i−1])%K=0,即 s [ j ] % K = s [ i − 1 ] % K s[j] \% K = s[i -1] \% K s[j]%K=s[i−1]%K,也就是 s [ j ] s[j] s[j] 模 K K K 的余数 和 s [ i − 1 ] s[i-1] s[i−1] 模 K K K 的余数 相等!

那么对于每一个 s [ j ] s[j] s[j],我们只需要找到前面与 s [ j ] % K s[j] \% K s[j]%K 相同的前缀和的个数即可。

所以我们可以直接使用哈希表 m a p map map 来存储 s [ j ] % K s[j] \% K s[j]%K的出现次数。

为了不漏掉从第一个元素开始的 K K K倍区间的个数。初始时, m a p [ 0 ] = 1 map[0] = 1 map[0]=1。

时间复杂度: O ( n ) O(n) O(n)

C++代码:

cpp 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

using LL = long long;

int main(){
    int n,k;
    cin>>n>>k;
    
    vector<int> a(n);
    for(int i = 0;i < n;i++) cin>>a[i];
    
    unordered_map<int,int> cnt;
    cnt[0] = 1;
    
    LL sum = 0, ans = 0;
    for(auto x:a){
        sum += x;
        int t = sum % k;
        ans += cnt[t];
        cnt[t]++;
    }
    
    cout<<ans<<'\n';
}

Java代码:

java 复制代码
import java.util.*;
import java.io.*;

public class Main {
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static int n;
	
	public static void main(String[] args) throws Exception 
	{
		String[] str = in.readLine().split(" ");
		n = Integer.parseInt(str[0]);
		int k = Integer.parseInt(str[1]);
		
		int[] a = new int[n];
		for(int i = 0;i < n;i++) a[i] = Integer.parseInt(in.readLine().trim());
		
		Map<Long,Integer> map = new HashMap<>();
		map.put(0L, 1);
		long sum = 0, ans = 0;
		
		for(int i = 0;i < n;i++) {
			sum += a[i];
			long t = sum % k;
			ans += map.getOrDefault(t, 0);
			map.put(t, map.getOrDefault(t, 0) + 1);
		}
		
		System.out.println(ans);
	}
}
相关推荐
强盛小灵通专卖员1 小时前
分类分割详细指标说明
人工智能·深度学习·算法·机器学习
IT猿手5 小时前
基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
神经网络·算法·matlab·人机交互·无人机·强化学习·无人机三维路径规划
万能程序员-传康Kk8 小时前
旅游推荐数据分析可视化系统算法
算法·数据分析·旅游
PXM的算法星球8 小时前
【并发编程基石】CAS无锁算法详解:原理、实现与应用场景
算法
ll7788118 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
烨然若神人~8 小时前
算法第十七天|654. 最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
算法
爱coding的橙子8 小时前
每日算法刷题Day2 5.10:leetcode数组1道题3种解法,用时40min
算法·leetcode
程序媛小盐9 小时前
贪心算法:最小生成树
算法·贪心算法·图论
Panesle9 小时前
分布式异步强化学习框架训练32B大模型:INTELLECT-2
人工智能·分布式·深度学习·算法·大模型
多多*10 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle