原题:http://www.codechef.com/LTIME12/problems/DIVSUBS
题目大意:给定一段序列,求出其中一段和能整除N的序列长度并输出该序列。
/*******************************************************************************/
题目分析:
首先我们先来判断一下这道题的有解性,其中我们利用前缀和,1-n项一共有n个前缀和,然后我们对它取余,值分布在0-n-1,也有n个值。
当如果其中有两个值相等或有值=0,则输出。
我认为有两种可能,一种可能为1-n恰好映射0-n-1,则存在有sum值=0;
另一种不存在等于0,则n个数分布在1-n-1 这n-1个数里,则运用抽屉原理可得,必定有两相等,证明结束。
所以思想就是找两个sum[]对n取余的结果相等,或sum[i]%n==0.
如下代码:
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#define REP(i,n) for(int i=0; i<n; i++)
#define FOR(i,n) for(int i=1; i<=n; i++)
using namespace std;
#define N 100010
int mark[N],n,a[N],ansl,ansr;
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int flag=0,sum=0;
memset(mark,-1,sizeof(mark));
mark[sum]=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum=((sum+a[i])%n+n)%n;
if(mark[sum]>-1){
ansl=mark[sum]+1;
ansr=i;
break;
}
mark[sum]=i;
}
printf("%d\n",ansr-ansl+1);
for(int i=ansl; i<=ansr; i++)printf("%d%s",a[i],i==ansr?"\n":" ");
}
//while(1);
return 0;
}