设为首页 加入收藏

TOP

poj 2356
2015-07-20 18:04:34 来源: 作者: 【 】 浏览:2
Tags:poj 2356

题目大意就是先给出一个数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]%N=sum[j]%N,其中i!=j,不妨设j>i

则(sum[j]-sum[i])%N=0,故sum[j]-sum[i]是N的倍数

则只要输出从i+1~j的所有的a的值就是答案

代码如下:

#include
  
   
#include
   
     int main() { int sum[1001000],flag[10010],a[10010],str[10010]; int n,i,j,t; while(scanf("%d",&n)!=EOF) { memset(sum,0,sizeof(sum)); memset(flag,0,sizeof(flag)); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) { sum[i]=sum[i-1]+a[i]; t=sum[i]%n; if(t==0) { printf("%d\n",i); for(j=1;j<=i;j++) printf("%d\n",a[j]); break; } else { if(flag[t]==0) { flag[t]=1; str[t]=i; } else { printf("%d\n",i-str[sum[i]%n]); for(j=str[sum[i]%n]+1;j<=i;j++) printf("%d\n",a[j]); break; } } } } return 0; } 
   
  


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇《C++ Primer Plus》学习笔记9 下一篇HDU 4870 Rating(高斯消元)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: