K倍区间(蓝桥杯每日一题)

简介: K倍区间(蓝桥杯每日一题)

K倍区间(蓝桥杯每日一题)

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

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

输入格式

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

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

输出格式

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

数据范围

1≤N,K≤100000

,

1≤Ai≤100000

输入样例:

5 2

1

2

3

4

5

输出样例:

6

算法思路

这个题算得上是前缀和的一个应用

这里想要知道一个区间是否为k的倍数,需要对每一个前缀和区间进行计数

这个理论就是对于一个区间[l, r],

(sum[i]-sum[j])%k=0,那么有sum[i]%k-sum[j]%k=0,可以推导出

sum[r] % k 和 sum[l-1] % k 的余数如果相等

那么sum[r] - sum[l-1]的差值必然是k的倍数

这样就可以理解ans += res[sum[i]]的含义了

res[sum[i]]想要可以被ans+=需要满足后面的前缀和%k之后

获得了同样的一个结果,因为每次的res[sum[i]]的结果都会++,统计

不同的res[sum[i]的出现次数,一旦后面这个结果触发了

ans += res[sum[i]]这个条件,那么就代表出现了至少一个区间[l,r]

使得满足题目的条件是k的倍数

最后的结果还需要加上res[0],这里指的是某个数是k的倍数,ans存放的是至少有两个数的区间。

C++

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
int sum[N], a[N], res[N];
int n, k;
ll ans = 0;
/*
这个题算得上是前缀和的一个应用
这里想要知道一个区间是否为k的倍数,需要对每一个前缀和区间进行计数 
这个理论就是对于一个区间[l, r],
(sum[i]-sum[j])%k=0,那么有sum[i]%k-sum[j]%k=0,可以推导出
sum[r] % k 和 sum[l-1] % k 的余数如果相等
那么sum[r] - sum[l-1]的差值必然是k的倍数 
这样就可以理解ans += res[sum[i]]的含义了
res[sum[i]]想要可以被ans+=需要满足后面的前缀和%k之后
获得了同样的一个结果,因为每次的res[sum[i]]的结果都会++,统计
不同的res[sum[i]的出现次数,一旦后面这个结果触发了
ans += res[sum[i]]这个条件,那么就代表出现了至少一个区间[l,r]
使得满足题目的条件是k的倍数 
最后的结果还需要加上res[0],这里指的是某个数是k的倍数,ans存放的是至少有两个数的区间。
*/
int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; ++ i)
    {
        cin >> a[i];
        sum[i] = (sum[i - 1] + a[i]) % k;
        // cout << "sum[i]:" << sum[i] << endl;
        ans += res[sum[i]];
        res[sum[i]] ++;
    }
    cout << ans + res[0] << endl;
    return 0;
}

Java

这个题算得上是前缀和的一个应用

这里想要知道一个区间是否为k的倍数,需要对每一个前缀和区间进行计数

这个理论就是对于一个区间[l, r],

(sum[i]-sum[j])%k=0,那么有sum[i]%k-sum[j]%k=0,可以推导出

sum[r] % k 和 sum[l-1] % k 的余数如果相等

那么sum[r] - sum[l-1]的差值必然是k的倍数

这样就可以理解ans += res[sum[i]]的含义了

res[sum[i]]想要可以被ans+=需要满足后面的前缀和%k之后

获得了同样的一个结果,因为每次的res[sum[i]]的结果都会++,统计

不同的res[sum[i]的出现次数,一旦后面这个结果触发了

ans += res[sum[i]]这个条件,那么就代表出现了至少一个区间[l,r]

使得满足题目的条件是k的倍数

最后的结果还需要加上res[0],这里指的是某个数是k的倍数,ans存放的是至少有两个数的区间。

import java.util.*;
public class Main
{
static int N = 100010;
static int [] sum = new int [N];
static int [] a = new int [N];
static int [] res = new int [N];
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int n, k, ans = 0;
n = in.nextInt();
k = in.nextInt();
for (int i = 1; i <= n; ++ i)
{
a[i] = in.nextInt();
sum[i] = (sum[i - 1] + a[i]) % k;
ans += res[sum[i]];
res[sum[i]] ++;
}
System.out.println(ans + res[0]);
}
}
相关文章
|
7月前
|
C语言
浙大版《C语言程序设计(第3版)》题目集 练习8-2 计算两数的和与差 (10分)
浙大版《C语言程序设计(第3版)》题目集 练习8-2 计算两数的和与差 (10分)
【LeetCode-每日一题】-16. 最接近的三数之和
【LeetCode-每日一题】-16. 最接近的三数之和
【力扣每日一题:2-20】697. 数组的度【简单】
【力扣每日一题:2-20】697. 数组的度【简单】
|
算法
代码随想录算法训练营第三十八天 | LeetCode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
代码随想录算法训练营第三十八天 | LeetCode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
58 0
|
C++
蓝桥杯 2240. 买钢笔和铅笔的方案数c++解法
蓝桥杯 2240. 买钢笔和铅笔的方案数c++解法
142 0
|
人工智能
蓝桥杯:k倍区间
蓝桥杯:k倍区间
63 0
|
机器人 Java Python
leetcode每日一题.200:岛屿数量
leetcode每日一题.200:岛屿数量
83 0
leetcode每日一题:746. 使用最小花费爬楼梯
leetcode每日一题:746. 使用最小花费爬楼梯
【蓝桥杯集训·每日一题】AcWing 3625. 幂次方
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 快速幂
69 0
|
人工智能 算法 测试技术
【寒假每日一题】AcWing 4644. 求和(补)
目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
85 0