算法竞赛入门经典第二章习题解答
本章的题目需用文件输入输出,如果题目代号为abc,那么输入文件为abc.in,输出文件为abc.out。如果对文件操作不熟练,请尽量把fopen和freopen两种方法都尝试一下。
注:本次解答中前4题给出两种方法,第五题采用fopen方法,其余均采用重定向方法。
习题2-1 位数(digit)
问题描述:输入一个不超过10^9的正整数,输出它的位数。例如12735的位数是5.请不要使用任何数学函数,只用四则运算和循环语句实现。
重定向版:
#define LOCAL #include<iostream> #include<cstdlib> #include<cstdio> using namespace std; int main() { #ifdef LOCAL freopen("digit.in","r",stdin); freopen("digit.out","w",stdout); #endif // LOCAL int n,cnt=1; scanf("%d",&n); while(n/10) { cnt++; n/=10; } printf("位数:%d\n",cnt); }
fopen版:
#include<stdio.h> int main() { FILE *fin,*fout; fin=fopen("digit.in","rb"); fout=fopen("digit.out","wb"); int n,cnt=1; fscanf(fin,"%d",&n); while(n/10) { cnt++; n/=10; } fprintf(fout,"位数:%d\n",cnt); fclose(fin); fclose(fout); return 0; }
习题2-2 水仙花数(daffodil)
问题描述:输出100~999中所有的水仙花数。若三位数ABC满足ABC=A^3+B^3+C^3;则称其为水仙花数,例如153=1^3+5^3+3^3,所以153是水仙花数。
重定向版:
#define LOCAL #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; int main() { #ifdef LOCAL freopen("daffodil.in","r",stdin); freopen("daffodil.out","w",stdout); #endif // LOCAL int a=0,b=0,c=0; for(int i=100;i<=999;i++) { a=i%10; b=i/10%10; c=i/100; if(i==(pow(a,3)+pow(b,3)+pow(c,3))) { printf("%d ",i); } } printf("\n"); }
fopen版:
#include<cstdio> #include<cmath> #include<cstdlib> #include<iostream> #include<fstream> using namespace std; int main() { FILE *fout; fout=fopen("daffodil.out","wb"); int a=0,b=0,c=0; for(int i=100;i<=999;i++) { a=i%10; b=i/10%10; c=i/100; if(i==(pow(a,3)+pow(b,3)+pow(c,3))) { fprintf(fout,"%d ",i); } } fprintf(fout,"\r\n"); fclose(fout); }
习题2-3 韩信点兵(hanxin)
问题描述:相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排德变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入三个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。
重定向版:
#define LOCAL #include<iostream> #include<cstdio> #include<cstdlib> using namespace std; int a,b,c; int main() { #ifdef LOCAL freopen("hanxin.in","r",stdin); freopen("hanxin.out","w",stdout); #endif // LOCAL while(scanf("%d%d%d",&a,&b,&c)==3) { bool flag=false; int num; for(int i=10;i<=100;i++) { if(i%3==a&&i%5==b&&i%7==c) { flag=true; num=i; break; } } if(flag==true) { printf("%d\n",num); } else { printf("No answer\n"); } } }
fopen版:
#include<iostream> #include<fstream> #include<stdio.h> using namespace std; int main() { FILE *fin,*fout; fin=fopen("hanxin.in","rb"); fout=fopen("hanxin.out","wb"); int a,b,c; while(fscanf(fin,"%d%d%d",&a,&b,&c)==3) { bool flag=false; int num; for(int i=10;i<=100;i++) { if(i%3==a&&i%5==b&&i%7==c) { flag=true; num=i; break; } } if(flag==true) { fprintf(fout,"%d\r\n",num); } else { fprintf(fout,"No answer\r\n"); } } fclose(fin); fclose(fout); return 0; }
习题2-4 倒三角形(triangle)
问题描述:输入正整数n<=20,输出一个n层的倒三角形。例如n=5时输出如下:
#########
#######
#####
###
#
重定向版:
#define LOCAL #include<iostream> #include<stdlib.h> #include<stdio.h> using namespace std; int main() { #ifdef LOCAL freopen("triangle.in","r",stdin); freopen("triangle.out","w",stdout); #endif // LOCAL int n; scanf("%d",&n); for(int i=1;i<=n;i++) { for(int j=1;j<i;j++) { printf(" "); } for(int j=1;j<=(n-i+1)*2-1;j++) { printf("#"); } printf("\n"); } }
fopen版:
#include<iostream> #include<stdlib.h> #include<fstream> #include<stdio.h> using namespace std; int main() { FILE *fin,*fout; fin=fopen("triangle.in","rb"); fout=fopen("triangle.out","wb"); int n; fscanf(fin,"%d",&n); for(int i=1;i<=n;i++) { for(int j=1;j<i;j++) { fprintf(fout," "); } for(int j=1;j<=(n-i+1)*2-1;j++) { fprintf(fout,"#"); } fprintf(fout,"\r\n"); } }
问题描述:输入一个正整数n,然后读取n个正整数a1,a2,a3.......an,最后再读取一个正整数m。统计a1,a2,a3........an中有多少个整数的值小于m。
提示:如果重定向和fopen都可以使用,那个比较方便。
选择fopen,因为fopen可以反复打开并读写文件。
fopen版:
#include<stdio.h> #include<stdlib.h> #include<fstream> int main() { FILE *fin,*fout; fin=fopen("stat.in","rb"); fout=fopen("stat.out","wb"); int n,a[10000]; fscanf(fin,"%d",&n); for(int i=0;i<n;i++) { fscanf(fin,"%d",&a[i]); } int m; fscanf(fin,"%d",&m); int cnt=0; for(int i=0;i<n;i++) { if(a[i]<m) { cnt++; } } fprintf(fout,"%d\r\n",cnt); fclose(fin); fclose(fout); }
习题2-6 调和级数(harmony)
问题描述:输入正整数n,输出H(n)=1+1/2+1/3+......+1/n的值,保留三位小数。例如n=3时,答案为1.7=833。
重定向方法:
#define LOCAL #include<stdio.h> #include<stdlib.h> #include<iostream> using namespace std; int main() { #ifdef LOCAL freopen("harmony.in","r",stdin); freopen("harmony.out","w",stdout); #endif // LOCAL int n; scanf("%d",&n); double res=0; for(int i=1;i<=n;i++) { res+=1.0/i; } printf("%.3lf\n",res); return 0; }
习题2-7 近似计算(approximation)
问题描述:计算PI/4=1-1/3+1/5-1/7+......,直到最后一项小于10^(-6)。
重定向方法:
#define LOCAL #include<stdio.h> #include<stdlib.h> #include<iostream> #include<cmath> using namespace std; int main() { #ifdef LOCAL freopen("approximation.in","r",stdin); freopen("aproximation.out","w",stdout); #endif // LOCAL int i=1,sign=-1; double res=1; do { res+=1.0/(2*i+1)*sign; i++; sign=-sign; }while(fabs(1.0/(2*i+1))>=10e-6); printf("%lf\n",4*res); return 0; }
习题2-8 子序列的和(subsequence)
问题描述:输入两个整数n<m<10^6,输出1/(n^2)+1/((n+1)^2)+.....+1/(m^2),保留5位小数。例如n=2,m=4时答案是0.42362;n=65536,m=655360时答案是0.00001。
注意:本题有陷阱。
重定向方法:
#define LOCAL #include<stdio.h> #include<stdlib.h> #include<iostream> #include<cmath> using namespace std; int main() { #ifdef LOCAL freopen("subsequence.in","r",stdin); freopen("subsequence.out","w",stdout); #endif // LOCAL int n,m,i; double res=0; scanf("%d%d",&n,&m); for(int i=n;i<=m;i++) res+=1.0/((long long)i*i; printf("%.5lf\n",res); return 0; }
问题描述:输入整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=10^6,c<=100。例如:a=1,b=6,c=4时应输出0.1667。
重定向方法:
#define LOCAL #include<stdio.h> #include<stdlib.h> #include<iostream> #include<cmath> using namespace std; int main() { #ifdef LOCAL freopen("decimal.in","r",stdin); freopen("decimal.out","w",stdout); #endif // LOCAL int a,b,c; scanf("%d%d%d",&a,&b,&c); cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(c); cout<<(double)a/(double)b; return 0; }
习题2-10 排列(permutation)
问题描述:用1,2,3...,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3,输出所有解。提示:不必太动脑筋。
重定向方法:
#define LOCAL #include<stdio.h> #include<stdlib.h> #include<iostream> #include<cmath> using namespace std; //用1,2,3……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出所有解。 #include <stdio.h> void result(int num, int &result_add, int &result_mul) { int i, j, k; i = num / 100; //百位 j = num / 10 % 10; //十位 k = num % 10; //个位 result_add += i + j + k; //分解出来的位数相加 result_mul *= i * j * k; //相乘 } int main() { #ifdef LOCAL // freopen("permutation.in","r",stdin); freopen("permutation.out","w",stdout); #endif // LOCAL int i, j, k; int result_add, result_mul; for(i = 123; i <=329; i++) { j = i * 2; k = i * 3; result_add = 0; result_mul = 1; result(i, result_add, result_mul); result(j, result_add, result_mul); result(k, result_add, result_mul); if(result_add == 45 && result_mul == 362880) printf("%d %d %d\n", i, j, k); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
posted on 2015-04-04 18:59 Tob__yuhong 阅读(253) 评论(0) 编辑 收藏 举报