感觉最后一题写一下挺爽的!
第十题
标题: k倍区间
给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。
你能求出数列中总共有多少个K倍区间吗?
输入
-----
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
输出
-----
输出一个整数,代表K倍区间的数目。
例如,
输入:
5 2
1
2
3
4
5
程序应该输出:
6
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include <xxx>
不能通过工程设置而省略常用头文件。
思路:用前缀和记录前面的数构成的区间[0,i]是否能够被k整除,然后[i,j]区间和能够被k整除的话就是 (sum[j] - sum[i]) % k== 0;,就相当于sum[i] == sum[j],其中sum[i],sum[j]是前机前缀和余k后的结果;
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll maxn = 1000000 + 10; int a[maxn]; int sum[maxn]; int n,m; map<int,int>ms; int main() { int Tcase; // scanf("%d",&Tcase); while( ~ scanf("%d%d",&n,&m)) { ms.clear(); int x = 0; int ans = 0; for(int i = 1; i <= n; i ++) { scanf("%d",&a[i]); x = (x+ a[i]) % m; // cout << x << "PP "; if(!x) ans ++; ms[x] ++; } map<int,int>::iterator it; for(it = ms.begin(); it != ms.end(); it ++) { int t = it -> second; if(t > 1) ans += (t - 1) * t / 2;; } cout << ans << endl; } return 0; }