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组装电脑配置单推荐报价格
下一篇:截断数组(蓝桥杯每日一题)
推荐阅读
留言与评论(共有 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]]的结果都会++ |