|
2012年2月10日
#include <stdio.h> int a[300]={0},b[300]={0},c[300]={0},ans[300]={0}; int main() { //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); int j,i,n; scanf("%d",&n); a[1]=1; b[1]=2; c[1]=4; if(n<4) { if(n==1)printf("1\n"); if(n==2)printf("2\n"); if(n==3)printf("4\n"); } else{ for(i=4;i<=n;i++) { for(j=1;j<=300;j++) { ans[j]+=a[j]+b[j]+c[j]; ans[j+1]+=ans[j]/10; ans[j]%=10; } for(j=1;j<=300;j++) { a[j]=b[j]; b[j]=c[j]; c[j]=ans[j]; ans[j]=0; } }
for(i=300;i>=0;i--) if(c[i])break; for(;i>=1;i--)printf("%d",c[i]); printf("\n"); } return 0; } 很简单的DP 但是竟然忘记高精度的写法了....
2011年11月8日
题目不是难,自定义一个函数,然后递归就可以了。 #include <stdio.h> long cout=0; void ans(n) { if(n!=0) { long i; for(i=1;n>0;i++) { n-=i;cout++;} if(n!=0) {cout--;ans(n-1+i);} } } int main() { //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); long m=1,n,i; scanf("%ld",&n); ans(n); printf("%ld",cout); return 0; }
2011年11月2日
很简单的一题,但是对DP很不熟悉,这好像也是第一次自己写dp的题目,写下错误吧。 #include <stdio.h> int main() { long n,m,i,j,a[30001]={0},v[26],w[26]; scanf("%ld%ld",&n,&m); for(i=0;i<m;i++) scanf("%ld%ld",&v[i],&w[i]); for(i=0;i<m;i++) for(j=n;j>=v[i];j--) if(a[j-v[i]]+v[i]*w[i]>a[j])a[j]=a[j-v[i]]+v[i]*w[i]; printf("%ld",a[n]); return 0; } 很基础的一题,但是在开始对n和m的含义弄混了,导致无输出。 后来在for(j=n;j>=v[i];j--) 中判断条件设成了j>0 没用弄清具体含义,下次要注意。
2011年10月29日
#include <stdio.h> char a[10000000]; int main() { long i,n=0,h=0,d=0; char c; scanf("%c",&c); while(c!='E')//存入胜负记录。判断是否结束,判断是否为换行。 { if(c!='\n') { n++; a[n]=c; } scanf("%c",&c); }
for(i=1;i<=n;i++) { if(a[i]=='W')h++; else d++; if(h>=11 && h-d>1 || d>=11 && d-h>1)//乒乓球的取胜规则。 { printf("%ld:%ld\n",h,d); h=0;d=0; } } printf("%ld:%ld\n",h,d); h=0;d=0; printf("\n"); for(i=1;i<=n;i++) { if(a[i]=='W')h++; else d++; if(h>=21 && h-d>1 || d>=21 && d-h>1) { printf("%ld:%ld\n",h,d); h=0;d=0; } } printf("%ld:%ld\n",h,d); return 0; }
二维数组空间覆盖,注意临界点和起始点。
#include <stdio.h> int main() { long j,i,a[101][101]={0},x[5],y[5],s1=0,s2=0,s3=0; for(i=1;i<=4;i++)scanf("%ld%ld",&x[i],&y[i]); for(i=x[1];i<x[2];i++) for(j=y[1];j<y[2];j++) a[i][j]=1; for(i=x[3];i<x[4];i++) for(j=y[3];j<y[4];j++) { if(a[i][j]==1)a[i][j]=3; else a[i][j]=1; } for(i=0;i<=100;i++) for(j=0;j<=100;j++) { if (a[i][j]==3)s1++; else if(a[i][j]==1)s2++; } printf("%ld %ld %ld\n",s1,s2,10000-s1-s2); return 0; }
我们按照由左而右的顺序移动纸牌。若第i堆纸牌的张数a[i]超出平均值,则移动一次(ans+1),将超出部分留给下一堆,既第i+1堆纸牌的张数增加a[i]-ave;若第i堆纸牌的张数a[i]少于平均值,则移动一次(ans+1),由下一堆补充不足部分,既第i+1堆纸牌的张数减少ave-a[i]; 问题是,在从第i+1堆中取出纸牌补充第i堆的过程中,可能会出现第i+1堆的纸牌数小于零(a[i+1]-(ave-a[i])<0 )的情况,但由于纸牌的总数是n的倍数,因此后面的堆会补充第i+1堆ave-a[i]-a[i+1]+ ave张纸牌,使其达到均分的要求。 我们在移动过程中,只是改变了移动的顺序,而移动的次数不变,因此此题使用该方法是可行的。 例如:1 2 27 我们从第二堆移出9张到第一堆后,第一堆有10张纸牌,第二堆剩下-7张纸牌,再从第三堆移动17张到第二堆,刚好三堆纸牌数都是10,最后结果是对的,从第二堆移出的牌都可以从第三堆得到。 此题的原理是贪心,从左到右让每堆牌向平均数靠拢。但负数的牌也可以移动,才是此题的关键。
#include <stdio.h> int a[101]={0}; int main() { long n,i,sum=0,d; scanf("%ld",&n); for(i=1;i<=n;i++) { scanf("%ld",&a[i]); sum+=a[i]; } d=sum/n; long count=0; for(i=1;i<=n-1;i++) { if(a[i]!=d) { a[i+1]-=d-a[i]; count++; } } printf("%ld",count); return 0; }
|