题目链接
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1103
题意
一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍数。
例如:N = 8,数组A包括:2 5 6 3 18 7 11 19,可以选2 6,因为2 + 6 = 8,是8的倍数。
题解
求出前缀和sum[i],表示前i个数的和模n下的值。
这n个前缀和的可能取值范围是0~n-1.
如果有sum[i]==0,那么选前i个数即可。
否则,将n个前缀和看作n个鸽子,将值为模1~模n-1看作n-1个鸽巢,那么至少有两个鸽子在一个鸽巢里。
而两个鸽子在一个鸽巢(假设sum[j]==sum[i]) 里说明第i+1~第j鸽数的和模n下为0.即第i+1~第j个数即为所取的数。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+7;
int vis[maxn];
int a[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
int sp=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(vis,0,sizeof(vis));
int sum=0,l=0,r=0;
for(int i=1;i<=n;i++)
{
sum=(sum+a[i]%n)%n;
if(sum==0)
{
l=1;
r=i;
break;
}
if(vis[sum])
{
l=vis[sum]+1;
r=i;
break;
}
vis[sum]=i;
}
printf("%d\n",r-l+1);
for(int i=l;i<=r;i++)
{
printf("%d\n",a[i]);
}
}
return 0;
}