您的位置:首页 > 健康 > 养生 > 北京高端建站公司_广州建设工程交易中心南沙交易部_南宁seo推广服务_深圳网络推广哪家公司好

北京高端建站公司_广州建设工程交易中心南沙交易部_南宁seo推广服务_深圳网络推广哪家公司好

2025/4/22 9:43:43 来源:https://blog.csdn.net/wuqingshun314159/article/details/147278014  浏览:    关键词:北京高端建站公司_广州建设工程交易中心南沙交易部_南宁seo推广服务_深圳网络推广哪家公司好
北京高端建站公司_广州建设工程交易中心南沙交易部_南宁seo推广服务_深圳网络推广哪家公司好

k倍区间

原题目链接

题目描述

给定一个长度为 N 的数列 A₁, A₂, ⋯, Aₙ,如果其中一段连续的子序列 Aᵢ, Aᵢ₊₁, ⋯, Aⱼ (i ≤ j) 之和是 K 的倍数,我们就称这个区间 [i, j]K 倍区间

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


输入描述

  • 第一行包含两个整数 NK (1 ≤ N, K ≤ 10⁵)。
  • 接下来 N 行,每行一个整数 Aᵢ (1 ≤ Aᵢ ≤ 10⁵),表示数列的每个元素。

输出描述

输出一个整数,表示 K 倍区间的数量。


输入样例

5 2
1
2
3
4
5

输出样例

6

c++代码

#include<bits/stdc++.h>
#include<stdio.h>using namespace std;typedef long long ll;
ll N, K, ans = 0;
unordered_map<int, int> mp;
vector<ll> arr;int main() {scanf("%lld %lld", &N, &K);arr = vector<ll>(N + 1, 0);for (ll i = 1; i <= N; i++) {scanf("%lld", &arr[i]);arr[i] += arr[i - 1];}if (K == 1) {printf("%lld", (N * (N - 1)) / 2 + N);return 0;}for (int i = 0; i <= N; i++) mp[arr[i] % K]++;for (auto it = mp.begin(); it != mp.end(); it++) ans += ((it->second * (it->second - 1)) / 2);printf("%lld", ans);return 0;
}//by wqs

算法解析

首先前缀和想得到吧

for (ll i = 1; i <= N; i++) {scanf("%lld", &arr[i]);arr[i] += arr[i - 1];
}

现在有了前缀和数组

我们要找两个端点i, j,使得

(arr[j] - arr[i]) % k == 0
假设arr[j] % k = c, arr[i] % k = d,
根据取模公式(arr[j] - arr[i]) % k = c - d。
也就是我们要让c - d = 0,也就是c == d。
现在我们的任务转换为求有多少组i,j满足arr[i] % k == arr[j] % k。
for (int i = 0; i <= N; i++) mp[arr[i] % K]++;
for (auto it = mp.begin(); it != mp.end(); it++) ans += ((it->second * (it->second - 1)) / 2);//排列组合
printf("%lld", ans);

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com