Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 5409 | Accepted: 2348 | Special Judge |
Description
Input
Output
If there are more than one set of numbers with required properties you should print to the output only one (preferably your favorite) of them.
Sample Input
5 1 2 3 4 1
Sample Output
2 2 3
题目大意就是先给出一个数N,接着再给出N个数,要你从这N个数中任意选择1个或多个数,使得其和是N的倍数
如果找不到这样的答案 则输出0
答案可能有多个,但只要任意输出一个解就行。
输出的第一行是选择元素的个数M,接着M行分别是选择的元素的值
刚开始的时候并不懂为什么这一题会是抽屉原理,分析后才明白,昨晚后更有体会
实际上此题一定有解,不存在输出0的结果
证明如下
我们可以依次求出a[0],a[0]+a[1],a[0]+a[1]+a[2],......,a[0]+a[1]+a[2]...+a[n];
假设分别是sum[0],sum[1],sum[2],......,sum[n]
如果存在某一项是N的倍数,则很好解,即可直接从第一项开始直接输出答案
但如果不存在,则sum[i]%N的值必定在[1,N-1]之间,又由于有n项sum,有抽屉原理:
把多于n个的物体放到n个抽屉里,则至少有一个抽屉里有2个或2个以上的物体。
则必定有一对i,j,使得sum[i]=sum[j],其中i!=j,不妨设j>i
则(sum[j]-sum[i])%N=0,故sum[j]-sum[i]是N的倍数
则只要输出从i+1~j的所有的a的值就是答案
然后就利用这个思路就可以直接的解出该题的答案
代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<algorithm>
using namespace std;
const int LEN=10005;
int arr[LEN];
int sum[LEN], mod[LEN];
//int path[LEN][LEN], vis[LEN], dis[LEN];
int main()
{
int n, i, j;
while( scanf("%d", &n)!=EOF )
{
scanf("%d", &arr[0]);
sum[0]=0;
sum[1]=arr[0];
memset(mod, -1, sizeof(mod));
for(i=1; i<n; i++)
{
scanf("%d", &arr[i]);
}
for(i=0; i<n; i++)
{
sum[i+1]=sum[i]+arr[i];
if( sum[i+1]%n==0 )
{
cout<<i+1<<endl;
for(j=0; j<=i; j++)
cout<<arr[j]<<endl;
break;
}
if( mod[sum[i+1]%n]!=-1 )
{
cout<<i-mod[sum[i+1]%n]<<endl;
for(j=mod[sum[i+1]%n]+1; j<=i; j++)
cout<<arr[j]<<endl;
break;
}
mod[sum[i+1]%n]=i;
}
}
return 0;
}