Acwing-1230 K倍区间 (普通)-第八届蓝桥杯省赛C++ B组

1230. K倍区间 - AcWing题库

输入样例:

5 2
1
2
3
4
5

输出样例:

6

样例理解:输入数组的元素个数,k为2,后面就是5个元素的数组

思路

 

思路

前缀和

直接上代码,不懂的再看后面的解释(自嗨)


//
// Created by 20116 on 2024/3/14.
//
#include <bits/stdc++.h>

using namespace std;

#define ll long long
const int N = 100005;


int n, k, a[N], sum[N], res[N], ans = 0;

int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        sum[i] = (sum[i - 1] + a[i]) % k; // 前缀和取模
        ans += res[sum[i]]; // 累加的是 不以开头的区间的k倍区间
        res[sum[i]]++; // 统计摸相同的区间
    }
    cout << ans + res[0]; // 最后加上前缀和模为0的区间,也就是以原数组开头的区间
    return 0;
}

举个栗子
1 2 3 4 5
前缀和后:
1 3 6 10 15
既然是k倍的区间,那就取模
1 1 0 0 1
模运算:发现右边的前缀和减去左边的前缀和就是中间的区间大小
然后进行取模
比如1-3,区间总和是1 + 3 + 6,取模就是0
2-5, 区间总和就是2的前缀和减去5的前缀和,也就是15 - 3 = 12
取模就是0,意味着2-5,就是k倍区间
再回来看数组的前缀和取模
1 1 0 0 1
发现第2和第5的前缀和取模的加起来再取模正是0,也就是2-5就是k倍区间
还有1-2,1-5,2-5,3-4是符合这个条件的
发现有点和最开始的k倍区间不太一致
实际上就是a-b区间内的区间也就是右边的减去左边的区间
比如1-2就是2,
1-5就是2-5
2-5就是3-5
3-4就是4
就是(x, y]的样子左开右闭区间
这就ok了,ok了吗,还有两个区间呢
那就是前缀和啦,所以就需要加上两个0了
有点不太理解啊
那就在数组前面加上一个0吧
也就是
0 1 1 0 0 1
发现了华点!
原来之前没有把第一个数字开始的区间给算进去了
所以在最后的结果加上了sum[0]了

posted on 2024-03-15 00:32  Hex酱  阅读(18)  评论(0)    收藏  举报

导航