N的倍数
一个长度为N的数组A,从A中选出若干个数,使得这些数的和是N的倍数。
例如:N = 8,数组A包括:2 5 6 3 18 7 11 19,可以选2 6,因为2 + 6 = 8,是8的倍数。
Input
第1行:1个数N,N为数组的长度,同时也是要求的倍数。(2 <= N <= 50000)
第2 - N + 1行:数组A的元素。(0 < Aii <= 10^9)
Output
如果没有符合条件的组合,输出No Solution。
第1行:1个数S表示你所选择的数的数量。
第2 - S + 1行:每行1个数,对应你所选择的数。
Sample Input
8
2
5
6
3
18
7
11
19
Sample Output
2
2
6
思路:
真的是一道神奇的题目,神奇的算法,听了题解之后五分钟能切完的题目……
首先记录一下每一项的前缀和,然后再记录一下前缀和模n的值。
对于某两项前缀和,若题目模n的值相同,则说明这两项之间的数的和模n为0。
若任意两项前缀和模n的值都不相同,由于一共有n个前缀和,他们%n又都不相同,则余数肯定是0~n-1,也就是说肯定有某项前缀和%n=0。。。
%%%%%%%%%%%%
代码如下:
#include<bits/stdc++.h>
#define ll long long
#define maxn 50005
int n;
ll a[maxn];
ll sum[maxn];
ll mod[maxn];
void solve()
{
int i;
for(i=1;i<=n;i++)
{
if(mod[i]==0)
{
printf("%d\n",i);
int j;
for(j=1;j<=i;j++)
printf("%lld\n",a[j]);
return ;
}
int j;
for(j=1;j<i;j++)
{
if(mod[j]==mod[i])
{
printf("%d\n",i-j);
int k;
for(k=j+1;k<=i;k++)
printf("%lld\n",a[k]);
return ;
}
}
}
}
int main()
{
while(~scanf("%d",&n))
{
int i;
sum[0]=0;
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
mod[i]=sum[i]%n;
}
solve();
}
return 0;
}