http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1350
1350.幸运数组
1350.幸运数组
Time Limit: 2000 MS
Memory Limit: 65536 K
Total Submissions: 221 (61 users) Accepted: 56 (44 users)
[ My Solution]
Total Submissions: 221 (61 users) Accepted: 56 (44 users)
[ My Solution]
Description
doraemon有一个幸运数字K, 并且对于一个数组, 若其和能被K整除, 则称该数组为幸运数组。现在他想知道, 给定一个长度为n且由正整数构成的数组, 它有多少个子数组为幸运数组呢? 其中, 子数组的定义为a[i:j](即a[i] ,a[i + 1], …… ,a[j], 其中1 <= i <= j <= n)
Input
输入的第一行有2个整数n和K(1 <= n <= 50,000, 1 <= K <= 1,000,000,000),分别代表数组的长度和幸运数字,接下来的一行有n个正整数ai(1 <= i <= n, 1 <= ai <= 1,000,000,000), 代表数组的元素。
Output
输出的一个数字, 代表存在的幸运子数组的个数。
Sample Input
5 6
1 2 3 4 5
Sample Output
2
Hint
2个幸运子数组分别为:
a[1:3] : a[1] + a[2] + a[3] = 6
a[3:5] : a[3] + a[4] + a[5] = 12
Source
doraemon @ xmu
上面的代码 是看一个大神写的
阿弥陀佛 哎 自己搞的超时 超时的那种 就是把所有和存进 sum 暴力求
上面大神的思路是:
求出所有的和 存进sum 然后对sum求余 那么余数相同的相减之后为0 也就是说(sumi%k)-(sumj%k)=0 也就是说(sumi-sumj)
%k=0 所以我们只要把所有的sum进行求余 之后如果余数相同 那么2者之间的数就能被k整出(不包括第i个,包括第j个)
#include<stdio.h>
#include<iostream>
#include<map>
using namespace std;
long long cou;
long long i,j,t,n,k,s;
map<long long,int> mapAns;
map<long long,int>::iterator iter;
int main()
{
while(scanf("%lld %lld",&n,&k)!=EOF)
{
mapAns[0]=1;
for(i=1;i<=n;i++)
{
scanf("%lld",&t);
s+=t;
if(s>=k)s=s%k;
mapAns[s]++;
}
for(iter=mapAns.begin();iter!=mapAns.end();++iter)
{
t=iter->second;
if(t>1)
{
cou+=t*(t-1)/2;
}
}
printf("%lld",cou);
}
return 0;
}
上面的代码 是看一个大神写的
阿弥陀佛 哎 自己搞的超时 超时的那种 就是把所有和存进 sum 暴力求
上面大神的思路是:
求出所有的和 存进sum 然后对sum求余 那么余数相同的相减之后为0 也就是说(sumi%k)-(sumj%k)=0 也就是说(sumi-sumj)
%k=0 所以我们只要把所有的sum进行求余 之后如果余数相同 那么2者之间的数就能被k整出(不包括第i个,包括第j个)
所以只要求出所有sum[i]的余数 看某个余数的个数 那么从中取任意2个 其之间的和都能被k整出 另外 要初始化 余数0的个数为1
原因 :对于 1 3 2 4 0 0 2 3 4 0 //这些每个余数的个数 自己可以根据这组数据去分析为什么