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]);
}
}
相关文章
|
1月前
lanqiao OJ k倍区间
lanqiao OJ k倍区间
9 0
|
1月前
|
算法
Leecode第十六题(最接近的三数之和)
这篇文章介绍了LeetCode第16题“最接近的三数之和”的题目要求、解题思路和代码实现,该算法题目要求从给定的整数数组中找出三个数,使它们的和最接近给定的目标值。
42 0
|
6月前
蓝桥备战--分糖果OJ2928 贪心 分类讨论
蓝桥备战--分糖果OJ2928 贪心 分类讨论
64 0
【LeetCode-每日一题】-16. 最接近的三数之和
【LeetCode-每日一题】-16. 最接近的三数之和
|
算法
代码随想录算法训练营第三十八天 | LeetCode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
代码随想录算法训练营第三十八天 | LeetCode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
48 0
|
人工智能
蓝桥杯:k倍区间
蓝桥杯:k倍区间
58 0
|
算法 C++ Python
每日算法系列【LeetCode 16】最接近的三数之和
每日算法系列【LeetCode 16】最接近的三数之和
|
算法 C++
每日算法系列【LeetCode 1363】形成三的最大倍数
每日算法系列【LeetCode 1363】形成三的最大倍数
leetcode每日一题:746. 使用最小花费爬楼梯
leetcode每日一题:746. 使用最小花费爬楼梯