原题链接:蓝桥杯2017年第八届真题-k倍区间
前缀和对 K 取模,统计答案的时候就是前面有多少个前缀和与该位置前缀和 % K 下相等,这样相减之后这些区间和 % K 下等于 0,也就是 K 的倍数了,我用分块来维护(数据结构学傻了,其实只需要开一个桶统计一个位置加入一个计数就可以了。
参考代码:
#ifndef LOCAL #include <bits/stdc++.h> #endif constexpr auto Inf = 0X3F3F3F3F; typedef long long LL; using namespace std; namespace IO { inline LL read() { LL o = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c > '/' && c < ':') { o = o * 10 + c - '0'; c = getchar(); } return o * f; } inline char recd() { char o; while ((o = getchar()) != 'C' && o != 'D'); return o; } } using namespace IO; const int SIZE = 1E5 + 7; int pre[SIZE], Arr[SIZE], N, K, bS; int BeL[SIZE], e[322][SIZE]; int Ask(int pos, int w) { int res = e[BeL[pos] - 1][w]; for (int L = bS * (BeL[pos] - 1) + 1; L < pos; L++) res += pre[L] == w; return res; } int main() { N = read(), K = read(), bS = sqrt(N); for (int pos = 1; pos <= N; pos++) BeL[pos] = (pos - 1) / bS + 1, Arr[pos] = read(), pre[pos] = (pre[pos - 1] + Arr[pos]) % K; /*for (int pos = 1; pos <= N; pos++) printf("%d ", pre[pos]); puts("");*/ for (int pos = 1; pos <= BeL[N]; pos++) { for (int u = 0; u < K; u++) e[pos][u] = e[pos - 1][u]; /*printf("L = %d, R = %d\n", bS * (pos - 1) + 1, min(bS * pos, N));*/ for (int L = bS * (pos - 1) + 1, R = min(bS * pos, N); L <= R; L++) e[pos][pre[L]]++; } /*for (int pos = 1; pos <= BeL[N]; pos++, puts("")) for (int u = 0; u < K; u++) printf("%d ", e[pos][u]);*/ LL ans = 0; for (int pos = 1; pos <= N; pos++) ans += Ask(pos, pre[pos]), ans += pre[pos] == 0; printf("%lld\n", ans); } /* 5 2 1 2 3 4 5 */
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复