蓝桥杯 6. k倍区间

打印 上一主题 下一主题

主题 1677|帖子 1677|积分 5031

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
k倍区间

原题目链接
题目描述

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

输入描述


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

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

输入样例
  1. 5 2
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
复制代码

输出样例
  1. 6
复制代码
c++代码
  1. #include<bits/stdc++.h>#include<stdio.h>using namespace std;typedef long long ll;ll N, K, ans &#6
  2. 1; 0;unordered_map<int, int> mp;vector<ll> arr;int main() {    scanf("%lld %lld", &N, &K);    arr &#6
  3. 1; vector<ll>(N + 1, 0);    for (ll i &#6
  4. 1; 1; i <&#6
  5. 1; N; i++) {        scanf("%lld", &arr[i]);        arr[i] +&#6
  6. 1; arr[i - 1];    }    if (K &#6
  7. 1;&#6
  8. 1; 1) {        printf("%lld", (N * (N - 1)) / 2 + N);        return 0;    }    for (int i &#6
  9. 1; 0; i <&#6
  10. 1; N; i++) mp[arr[i] % K]++;    for (auto it &#6
  11. 1; mp.begin(); it !&#6
  12. 1; mp.end(); it++) ans +&#6
  13. 1; ((it->second * (it->second - 1)) / 2);    printf("%lld", ans);    return 0;}//by wqs
复制代码
算法解析

起首前缀和想得到吧
  1. for (ll i &#6
  2. 1; 1; i <&#6
  3. 1; N; i++) {    scanf("%lld", &arr[i]);    arr[i] +&#6
  4. 1; arr[i - 1];}
复制代码
现在有了前缀和数组
我们要找两个端点i, j,使得
  1. (arr[j] - arr[i]) % k &#6
  2. 1;&#6
  3. 1; 0假设arr[j] % k &#6
  4. 1; c, arr[i] % k &#6
  5. 1; d,根据取模公式(arr[j] - arr[i]) % k &#6
  6. 1; c - d。也就是我们要让c - d &#6
  7. 1; 0,也就是c &#6
  8. 1;&#6
  9. 1; d。现在我们的任务转换为求有多少组i,j满意arr[i] % k &#6
  10. 1;&#6
  11. 1; arr[j] % k。
复制代码
  1. for (int i &#6
  2. 1; 0; i <&#6
  3. 1; N; i++) mp[arr[i] % K]++;for (auto it &#6
  4. 1; mp.begin(); it !&#6
  5. 1; mp.end(); it++) ans +&#6
  6. 1; ((it->second * (it->second - 1)) / 2);//排列组合printf("%lld", ans);
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万万哇

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表