您现在的位置是:首页 > 编程 > 

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

2025-07-29 03:13:59
K倍区间(蓝桥杯每日一题) K倍区间(蓝桥杯每日一题)给定一个长度为 的数列,A1,A2,…A,如果其中一段连续的子序列 Ai,Ai+1,…Aj之和是 K的倍数,我们就称这个区间 [i,j]是 K倍区间。你能求出数列中总共有多少个 K倍区间吗?输入格式 第一行包含两个整数 和 K。以下 行每行包含一个整数 Ai。输出格式 输出一个整数,代表 K倍区间的数目。数据范围 1≤,K≤10

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

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

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

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

输入格式 第一行包含两个整数 和 K。

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

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

数据范围 1≤,K≤100000 , 1≤Ai≤100000

输入样例: 5 2 1 2 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++

代码语言:javascript代码运行次数:0运行复制
#include<bits/stdc++.h>
using namespace std;

ct int  = 1e5 + 10;
typedef long long ll;
int sum[], a[], res[];
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 = 100010; static int [] sum = new int []; static int [] a = new int []; static int [] res = new int []; public static void main(String[] args) { Scanner in = new Scanner(System.in); int n, k, ans = 0; n = (); k = (); for (int i = 1; i <= n; ++ i) { a[i] = (); sum[i] = (sum[i - 1] + a[i]) % k; ans += res[sum[i]]; res[sum[i]] ++; } println(ans + res[0]); } }

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:202-02-2,如有侵权请联系 cloudcommunity@tencent 删除统计intsum数据算法

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1147229.html

相关标签:无
上传时间: 2025-07-19 15:54:00
留言与评论(共有 13 条评论)
本站网友 创业投资引导基金
25分钟前 发表
res[]; int n
本站网友 外汇管理条例
15分钟前 发表
…A
本站网友 牙齿贴面
7分钟前 发表
r]
本站网友 福朋
14分钟前 发表
k; ll ans = 0; /* 这个题算得上是前缀和的一个应用 这里想要知道一个区间是否为k的倍数
本站网友 btk
10分钟前 发表
统计 不同的res[sum[i]的出现次数
本站网友 张茆博客
18分钟前 发表
*/ 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]
本站网友 视频设备租赁
2分钟前 发表
(sum[i]-sum[j])%k=0
本站网友 广州骏景花园
8分钟前 发表
因为每次的res[sum[i]]的结果都会++
本站网友 正佳广场美食
19分钟前 发表
那么就代表出现了至少一个区间[l
本站网友 esd是什么
3分钟前 发表
那么有sum[i]%k-sum[j]%k=0
本站网友 因素花
29分钟前 发表
r]
本站网友 番薯糖水
23分钟前 发表
因为每次的res[sum[i]]的结果都会++