一个长度为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
PS:抽屉定理,可以去网上看看这个定理。https://blog.youkuaiyun.com/qq_36553623/article/details/68961300。简单的说吧,这个题直接求前缀和。如果和能够直接整除n,那肯定可以找到,直接输出。就对前缀和数组对n取余。若求余后两个数组两个数相等,则相等的两个位置中的数,加起来肯定是n的倍数。
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<cmath>
const int maxn=1e5+10;
const int mod=1e9+7;
#define me(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
int main()
{
int n,a[maxn];
ll num[maxn];me(num);
cin>>n;
int flog=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
num[i]=num[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
num[i]%=n;
if(!num[i])
{
cout<<i<<endl;
for(int j=1;j<=i;j++)
cout<<a[j]<<endl;
return 0;
}
}
map<ll,int>q;
for(int i=1;i<=n;i++)
{
if(q[num[i]])
{
cout<<i-q[num[i]]<<endl;
for(int j=q[num[i]]+1;j<=i;j++)
cout<<a[j]<<endl;
flog=1;
break;
}
else
q[num[i]]=i;
}
if(!flog)
cout<<"No Solution"<<endl;
return 0;
}