紫书第二章习题题解
前言
刚学C不久,代码有些拙劣,大佬轻喷,也欢迎交流。以下代码均在DevC++(C11)上实现过。
题解
习题2-1 水仙花数(daffodil)
输出100~999中的所有水仙花数。若3位数ABC满足ABC=A³+B³+C³,则称其为水仙花数。例如 153=1³+5³+3³,所以153是水仙花数。
分析
要点在于取个位数,十位数以及百位数。
代码
#include<stdio.h>
int main()
{
for (int i = 100; i<1000; i++){
int a = i % 10;
int b = (i / 10) % 10;
int c = i / 100;
if (i == a * a * a + b * b * b + c * c * c) printf("%d\n", i);
}
return 0;
}
习题2-2 韩信点兵(hanxin)
相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入包含多组数据,每组数据包含3个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。输入到文件结束为止。
样例
样例输入:
2 1 6
2 1 3
样例输出:
Case 1: 41
Case 2:No answer
分析
这题难点就是输入多组数据吧,运用好scanf()函数的返回值为输入的项数。
代码
#include<stdio.h>
int main()
{
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
int a=0, b=0, c=0,t=0,kase=0;
while(scanf("%d %d %d", &a, &b, &c) == 3)
{
for (int i = 10;i < 100;i++)
{
if ((i % 3 == a ) && (i % 5 == b) && (i % 7 == c)) {
t = i;
break;}
else
t = 0;}
if (t != 0) printf("Case %d: %d\n", ++kase, t);
else printf("Case %d: No answer\n", ++kase);
}
return 0;
}
习题2-3 倒三角形(triangle)
输入正整数n<=20,输出一个n层的倒三角形。例如,输入n=5时输出如下:
#########
#######
#####
###
#
分析
要点在于每行前的空格,有多种写法,不唯一。
代码
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
for (int i = n; i != 0; i--)
{
for (int j = 0; n - i != j;j++)
{
printf(" ");
}
for (int k = 1; k <= (2 * i - 1); k++)
{
printf("*");
}
printf("\n");
}
return 0;
}
习题2-4 子序列的和(subsequence)
输入两个正整数 n<m<10^6,输出,保留5位小数。输出包含多组数据,结束标记为 n=m=0。提示:本题有陷阱。
样例
样例输入:
2 4
65536 655360
0 0
样例输出:
Case 1: 0.42361
Case 2: 0.00001
分析
题目所说的陷阱为乘法溢出的问题。
代码
#include<stdio.h>
int main()
{
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
int n = 0, m = 0, k = 0;
double sum;
while (scanf("%d %d", &n, &m) == 2 && n != 0 && m != 0)
{
for (int i = n; i <= m; i++)
{
sum += 1.0 / i /i;
}
printf("Case %d: %.5f\n", ++k ,sum);
sum = 0;
}
return 0;
}
习题2-5 分数化小数(decimal)
输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b≤10^6,c≤100。输入包含多组数据,结束标记为a=b=c=0。
样例
样例输入:
1 6 4
0 0 0
样例输出:
Case 1: 0.1667
分析
这题的难点在于精确度由输入的数据控制,不是以往的固定精确度,使用“*”修饰符来控制。
代码
#include<stdio.h>
#define fo
int main()
{
#ifdef fo
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif
int a = 0, b = 0, c = 0, kase=0;
double decimal=0.0;
while (scanf("%d %d %d", &a, &b, &c) == 3 && a != 0 && b != 0 && c != 0)
{
decimal = (double)a / b;
kase++;
printf("Case %d: %.*f", kase, c, decimal);
}
return 0;
}
习题2-6 排列(permutation)
用 1,2,3,……9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3。按照”abc def ghi”的格式输出所有解,每行一个解。提示:不必太动脑筋。
分析
由于还没开始学第三章的内容,所在这里想到的是暴力求解,然后再优化。首先能组成的最大三位数为987,所以abc最大为987的三分之一即329。循环的范围即从能组成的最小三位数123到329。而为了保证每个数恰好只使用一次,因为还没学第三章的内容,所以这里使用9个数的和与积来判断九个数是否恰好使用一次。
代码
#include<stdio.h>
#include<time.h>
int main()
{
int a=0, b=0, c=0, sum=0, product=1;
for (int i=123;i<=329;i++)
{
a = i;
b = 2 * a;
c = 3 * a;
sum = (a % 10) + (a / 10 % 10) + (a / 100) + (b % 10) + (b / 10 % 10) + (b / 100) + (c % 10) + (c / 10 % 10) + (c / 100);
product = (a % 10) * (a / 10 % 10) * (a / 100) * (b % 10) * (b / 10 % 10) * (b / 100) * (c % 10) * (c / 10 % 10) * (c / 100);
if ((sum == 45) && (product == 362880)) printf("%d %d %d\n", a, b, c);
}
return 0;
}
评论列表