hdu 1808 || poj 3370原题链接:点击打开链接
思路(转):
首先简单说一下鸽巢原理,就是有n+1个球,放在n个盒子中,那么至少有一个盒子有两个或更多的球。
而这两道题正是运用了这个思想。先对数列求前N项和,有s1=a1,s2=a1+a2,
s3=a1+a2+a3,......,sn=a1+a2+a3+...+an。若其中有和可以整除m,那么即可得出答案,否则,所得的余数只会是1,2,...,n-1,因此,必存在至少两个数模除m后有相同余数r,即si=b*m+r,sj=c*m+r,则si-sj=(b-c)*m。则序列ai到aj的和即为所求。
code:
#include<stdio.h>
#include<string.h>
int yushu[100010],d[100010];
int main()
{
int m,i,j,ans,c,n,sum;
while(scanf("%d%d",&c,&n)!=EOF)
{
if(c==0&&n==0)
break;
memset(yushu,0,sizeof(yushu));
for(i=1;i<=n;i++)
scanf("%d",&d[i]);
int st,ed;
sum=0;
for(i=1;i<=n;i++)
{
sum=(sum+d[i])%c;
if(sum==0)
{
st=1;
ed=i;
break;
}
else if(yushu[sum])
{
st=yushu[sum]+1;
ed=i;
break;
}
else
yushu[sum]=i;
}
for(i=st;i<=ed;i++)
printf(i==ed?"%d\n":"%d ",i);
}
return 0;
}
hdu 1205:
原题链接:点击打开链接
思路:找出数量最多的某类糖果(m个),剩下sum-m个,则能产生(sum-m+1)个位置来放置数量最多的糖果
如果m>(sum-m+1)则说明不能将数量最多的吃完,反过来看,m个数量最多的某类糖果,相当于有m块挡板,产生了m+1个空格可以用来放置其余的糖果,这些数量不太多的糖果 也可以看做是将之前产生的挡板的厚度增加的。
比如 :m1x1n1 m2n2 m3n3 m4n4 m5n5;
其中 x1就相当于将前一个挡板加厚了 只要能保证数量最多的糖果被吃完 就能被吃完
code:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
using namespace std;
int main()
{
int cas;
scanf("%d",&cas);
__int64 n,maxx,sum,i,t;
while(cas--)
{
sum=0;
maxx=-1;
scanf("%I64d",&n);
for(i=0;i<n;i++)
{
scanf("%I64d",&t);
sum+=t;
maxx=max(maxx,t);
}
if(maxx>(sum-maxx+1))
printf("No\n");
else
printf("Yes\n");
}
return 0;
}
poj 2356:与poj3370 一样 除了输出之外。
code:
#include<stdio.h>
#include<string.h>
int d[10010],yushu[10010];
int main()
{
int i,sum=0,st,ed,n;
while(scanf("%d",&n)!=EOF)
{
memset(yushu,0,sizeof(yushu));
for(i =1 ;i<=n;i++)
scanf("%d",&d[i]);
for(i=1;i<=n;i++)
{
sum=(sum+d[i])%n;
if(sum==0)
{
st=1;
ed=i;
break;
}
else if(yushu[sum])
{
st=yushu[sum]+1;
ed=i;
break;
}
else
yushu[sum]=i;
}
printf("%d\n",ed-st+1);
for(i=st;i<=ed;i++)
printf("%d\n",d[i]);
}
return 0;
}