简单的说就是已知c,n和n个无序数字,要求这n个数中那些的和能被c整除==
联想到课件给的
例题: POJ 2356
题意:
给定n个数,求其中的任意一个非空子集满足集合中的每个元素值加和正好是n的倍数 。
分析:
把前缀和统计出来对n取模,任意两个相等的sum [i], sum [j] ,[i ,j ]内的数的和都满足这个条件。
n个数对n取模,范围为[0~n-1],由抽屉原理可知,最少有一个数模n=0,或者两个数模n相等。
以及题目已知的c<=n得出结论 这两个题是一样一样一样的~~~
因为根据抽屉原理,一定能找到连续的一段数字串使得其和为c的倍数,于是乎很傻很天真的照着课件敲上去,华丽丽的超时了~
发现这样太满了,肿么破……数组,和,找相等==哈希啊!!!
#include<iostream>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include<cstring>
using namespace std;
const int N=100009;
int n,m;
int a[N];
int sum[N];
int hash[N];
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
memset(hash,0,sizeof(hash));
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
}
int s=1,t=1;
sum[0]=0;
for(int i=1;i<=m;i++)
{
sum[i]=(sum[i-1]+a[i])%n;
//cout<<i<<" "<<sum[i]<<endl;
if(sum[i]==0)
{
t=i;
break;
}
if(hash[sum[i]]>0)
{
s=hash[sum[i]]+1;
t=i;
break;
}
hash[sum[i]]=i;
}
for(int i=s;i<t;i++)
printf("%d ",i);
printf("%d\n",t);
}
return 0;
}
这个题还可以hash数组只用来标记有或者没有出现过这个余数,即布尔型就可以了
AC代码如下
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool num[1000101];
int a[1000010],c,n,sum[1000010];
int main()
{
// freopen("cin.txt","r",stdin);
while(~scanf("%d%d",&c,&n))
{
if(c==0&&n==0) break;
int st=-1,ed=-1;
memset(num,false,sizeof(num));
sum[0]=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if(ed==-1) {
sum[i]=(a[i]%c+sum[i-1])%c;
if(!sum[i]) {st=1;ed=i;}
else if(num[sum[i]]) ed=i;
num[sum[i]]=true;
// printf("i=%d %d\n",i+1,sum[i]);
}
}
for(int i=1;i<=n&&(st==-1);i++)
{
if(sum[i]==sum[ed]){
st=i+1;
break;
}
}
printf("%d",st);
for(int i=st+1;i<=ed;i++)
printf(" %d",i);
printf("\n");
}
return 0;
}
之前有一个小问题没注意到 就是可能这样余数是0的话 从第一个数开始 wa了好多次 就像酱紫是不对的
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool num[1000101];
int a[1000010],c,n,sum[1000010];
int main()
{
// freopen("cin.txt","r",stdin);
while(~scanf("%d%d",&c,&n))
{
if(c==0&&n==0) break;
int st,ed=-1;
memset(num,false,sizeof(num));
sum[0]=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if(ed==-1) {
sum[i]=(a[i]%c+sum[i-1])%c;
if(num[sum[i]]) ed=i;
num[sum[i]]=true;
// printf("i=%d %d\n",i+1,sum[i]);
}
}
for(int i=1;i<=n;i++)
{
if(sum[i]==sum[ed]){
st=i+1;
break;
}
}
printf("%d",st);
for(int i=st+1;i<=ed;i++)
printf(" %d",i);
printf("\n");
}
return 0;
}