相对第一天,第二天的已经有点挑战了。例题和习题已经出现了真正的竞赛题目——仅使用简单变量和基本的顺序、分支和循环结构就可以解决很多问题。
习题
- 水仙花数。输出100~999所有的水仙花数。ABC=A3+B3+C3即为水仙花数。eg:153就是水仙花数,153=13+53+33
- 韩信点兵。相传韩信清点士兵从来不直接清点。只要让士兵三人一排、五人一排、七人一排地变换队形,每次只要看队尾的几个人就可以得出士兵的数量。输入包含多组数据,每组数据包含3个非负整数a,b,c,表示每种队列排尾的人数(a<3,b<5,c<7),输出为符合的人数最小值(全部不符合就输出No answer)。总人数不小于10,不超过100。输入到文件结束为止。
样例输入:
2 1 6
2 1 3
样例输出:
Case 1: 41
Case 2:No answer - 倒三角形。输入正整数n(n<=20),输出一个n层倒三角形。例如
样例输入:
5
样例输出:
- 子序列的和。输入两个正整数n<m<106,输出1/n2+1/(n+1)2+…+1/m2,保留5位小数。输入包含多组数据,结束标记为n=m=0,提示:本题有陷阱。
样例输入:
2 4
65536 655360
0 0
样例输出:
Case 1:0.42361
Case 1:0.00001 - 分数化小数。输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=106,c<=100。输入包含多组数据,结束标记为a=b=c=0。
样例输入
1 6 4
0 0 0
样例输出:
Case 1:0.1667 - 排列。用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3。按照abc def ghi的格式输出所有解,每行一个解。提示:不必太动脑筋。
以下的代码都是自己修改,逐步逐步写出来的,也有很多错误的地方,在论坛上也问了很多大佬才逐步修改完成的代码,谢谢那些无私教导自己的大佬。若有更好的代码,可以在评论里面分享!
// 1,水仙花数
//很常见的题目了,自己大一遇到这个题目三四次了。。。
#include <stdio.h>
int main()
{
int a, b, c;
for(int i=100;i<=999;i++)
{
a = i/100%10;
b = i/10%10;
c = i%10;
if(a*a*a+b*b*b+c*c*c == i) printf("%d\n", i);
}
return 0;
}
// *2,韩信点兵
#define LOCAL
#include <stdio.h>
int main()
{
#ifdef LOCAL
freopen("data_1.in", "r", stdin);
freopen("data_1.out" ,"w", stdout);
#endif
int a, b, c, temp=0 ,count=0;
while(scanf("%d%d%d", &a, &b, &c) == 3) //scanf函数是输入几个数据就返回几,这里三个数据,就是scanf(...) == 3,自己一开始不会用,
{
temp = 0;
for(int i=10;i<=100;i++)
{
if((i%3 == a) && (i%5 == b) && (i%7 == c))
{
temp = 1;
printf("Case %d: %d\n", count, i);
break;
}
}
if(temp != 1) printf("Case %d: No answer\n", ++count);
}
return 0;
}
// 3.倒三角形
//以输入5为例,可以找出规律。
//输出" "的规律:第i行输出i-1个
//输出"#"的规律:第i行输出(n-i)*2+1个
#include<stdio.h>
int main()
{
int n;
scanf("%d", &n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i-1;j++)
printf(" ");
for(int j=(n-i)*2+1;j>0;j--)
printf("#");
printf("\n");
}
return 0;
}
// *4.子序列的和
#include <stdio.h>
int main()
{
int n, m, k=0;
double sum = 0.0;
while(scanf("%d%d", &n, &m) == 2 && (n || m))
{
sum = 0.0;
for(double i=n;i<=m;i++) //i若不是double类型,num计算的就是1/0了,导致sum最终输出1.#INF
{
double num = 1.0/(i*i);
sum += num;
}
printf("Case %d: %.5f\n", ++k, sum);
}
return 0;
}
// 5.分数化小数
//自己觉得难点在实现保留不固定的小数位
//百度Google也没有找到合适的解决办法,只找到了C++中使用函数解决的方法。
//自己通过论坛大佬的帮助解决了这一问题,就是使用*占位符
#include <stdio.h>
//#include <math.h>
int main()
{
int a, b, c, kase=0;
while(scanf("%d%d%d", &a, &b, &c) == 3 && (a || b || c))
{
double num = (double)a/b;
//double t = pow(10, c+1);
//int n = t * num;
//if(n%10 >= 5) n = n/10 + 1;
//else n = n/10;
printf("Case %d: %.*lf\n", ++kase, c, num); //++kase对应的是%d,c对应的是*,num对应的是%.lf,很好理解
}
return 0;
}
// 6.排列
//下面详细说
第6题是ACM的题目,自己第一次写确实写不来,自己写的代码什么输出都没有,Google了这道题,找到了解决方法:
这里我还是把我第一次写失败的代码截图出来吧,毕竟是自己写了很久的代码,也当是个教训了。
//错误代码
#include <stdio.h>
int main()
{
int n1,n2,n3;
for(int j=123;j<=333;j++)
{
int a = j/100;
int b = j/10%10;
int c = j%10;
int d = (2*j)/100;
int e = (3*j)/10%10;
int f = (2*j)%10;
int g = (3*j)/100;
int h = (3*j)/10%10;
int i = (3*j)%10;
if((a==0) || (b==0) || (c==0)) continue;
//自己感觉问题出在这里
if((a!=b) && (a!=c) && (a!=d) && (a!=e) && (a!=f) && (a!=g) && (a!=h) && (a!=i))
if((b!=c) && (b!=d) && (b!=e) && (b!=f) && (b!=g) && (b!=h) && (b!=i))
if((c!=d) && (c!=e) && (c!=f) && (c!=g) && (c!=h) && (c!=i))
if((d!=e) && (d!=f) && (d!=g) && (d!=h) && (d!=i))
if((e!=f) && (e!=g) && (e!=h) && (e!=i))
if((f!=g) && (f!=h) && (f!=i))
if((g!=h) && (g!=i))
if(h!=i)
printf("%d %d %d\n", i, 2*i, 3*i);
}
return 0;
}
//接下来是正确的代码:
#include <stdio.h>
//实现输入一个三位数,将三个位置上的数字累加存入result_add,累乘存入result_mul
void result(int num, int &result_add, int &result_mul) //num是传入值,其他两个是传出值,用来将传入的三位数三个组成数字累加和累乘。
{
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()
{
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) //保证9个数是1到9无重叠,result_add=1+2+...+9,result_mul=1*2*...*9。
printf("%d %d %d\n", i, j, k);
}
return 0;
}
思考
题1:
修改程序,输出2,4,6,8,…,2n,每个一行。
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for(int i=1;i<=2n;i++)
printf("%d\n", i);
return 0;
}
- 修改for的条件,其他不改
- 修改循环体,其他不改
两种方法都写
// 1.修改条件的方法
for(int i = 2;i<=2*n;i+=2) //其他地方不动
// 2.修改循环体的方法
printf("%d\n",2*i); //其他地方不动
题2:
说出下面程序输出的数据
#include <stdio.h>
int main()
{
double i;
for(i=0;i!=10;i+=0.1)
printf("%.1f\n", i);
return 0;
}
先来预测一下,我一开始认为i从0一直加0.1,加到9.9的时候,再次+0.1,然后!=条件不满足,跳出循环,输出的应该就是0到9.9的一行行的数据。
但是,我们运行后,却出现了死循环。这是因为浮点数计算有误差,9.9+0.1!=10,可能等于0.9999999什么的,从而陷入死循环,从而输出大于10的数据。这里我们也知道了,用浮点数做条件的时候不要用不等于,用小于大于这些影响还是不大的,就像上面一个练习:子序列的和,for循环里的i就是double类型(保证1/(i*i)计算不为0)。
这节练习确实挺难的,但多写写,多了解一些思路应该就会了。