https://vjudge.net/contest/374932#problem/B
(题目链接如上)
题意:
给定邻居的糖果数,求糖果数和为c的倍数的邻居的下标
题解:
运用抽屉原理。
先求出数组a的前缀和sum;
sumk=a1+a2+a3+…+ak;
(1)若sumk==0,则直接取1~k的区间下标;
(2)若sumk!=0,则sumk%c的值r,r的取值在1~k-1;
而sum1,sum2,sum3…sumk有k个数,则至少有两个数相同;
即一定有sumi=sumj,也即sumi%c=sumj%c,移项后就是(sumj-sumi)%c=0,所以区间i+1到j的和可以整除c。
另外,这题直接n^2判断会超时,所以用vis数组记录,o(n)找到两个相同的sum。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
ll sum[100005];
int vis[100005];
int main(){
ll c,n,a;
while(scanf("%lld%lld",&c,&n)){
if(c==0&&n==0) break;
memset(vis,-1,sizeof(vis));
int flag=0,l,r;
for(int i=1;i<=n;i++){
scanf("%lld",&a);
sum[i]=(sum[i-1]+a)%c;
if(sum[i]==0){
flag=1;
l=1; r=i;
}
}
if(!flag){
for(int i=1;i<n;i++){
if(vis[sum[i]]){
l=vis[sum[i]]+1;
r=i;
break;
}
else vis[sum[i]]=i;
}
}
for(int i=l;i<=r;i++){
if(i==l) printf("%d",i);
else printf(" %d",i);
}
printf("\n");
}
return 0;
}