C/C++_循环结构程序设计练习

相对第一天,第二天的已经有点挑战了。例题和习题已经出现了真正的竞赛题目——仅使用简单变量和基本的顺序、分支和循环结构就可以解决很多问题。

习题

  1. 水仙花数。输出100~999所有的水仙花数。ABC=A3+B3+C3即为水仙花数。eg:153就是水仙花数,153=13+53+33
  2. 韩信点兵。相传韩信清点士兵从来不直接清点。只要让士兵三人一排、五人一排、七人一排地变换队形,每次只要看队尾的几个人就可以得出士兵的数量。输入包含多组数据,每组数据包含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
  3. 倒三角形。输入正整数n(n<=20),输出一个n层倒三角形。例如
    样例输入:
    5
    样例输出:
    在这里插入图片描述
  4. 子序列的和。输入两个正整数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
  5. 分数化小数。输入正整数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
  6. 排列。用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;
}
  1. 修改for的条件,其他不改
  2. 修改循环体,其他不改
    两种方法都写
// 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)。
在这里插入图片描述
这节练习确实挺难的,但多写写,多了解一些思路应该就会了。

1. 请写1个支付宝接龙红包程序. 随机产生1-100的随机数,作为红包金额. 让用户不断的去猜,直到猜正确为止.最后发给用户的红包金额是 红包金额/猜得次数. 2. 循环录入5个人的年龄并计算平均年龄,如果录入的数据出现负数或大于100的数,立即停止输入并报错. 3. 实现要求用户一直输入QQ号码和密码,只要不是123456、888888就一直提示要求重新输入,如果正确则提登录成功. 4. 1-100之间不能够被7整除的数的和. 5. 求1-200之间的所有的整数的累加和 6. 求1-100之间6的倍数的个数 7. 输入班级人数,然后依次输入学员成绩,计算班级学员的平均成绩和总成绩 8. 2006年培养学员80000人,每年增长25%,请问按此增长速度,到哪一年培训学员人数将达到20万人?*** 9. 从键盘输入10个数,求出最大数 10. 1000~ 5000之间有多少整数,其各位数字之和为5,分别是哪些数(例如整数2003的各位数字之和为 2+0+0+3 ,等于5)), 并统计满足条件的整数有多少个。 11. 求1-100中 是7的倍数 的数值之和 12. 求1-1000之间的所有的奇数之和 13.猜数字游戏. 随机产生1个1-100之间的数 让用户猜 当用户输入的数比产生的随机数大 就输出 猜大了 并让用户继续输入新的数.。 当用户输入的比产生的随机数小的时候 就输出 猜小了 并且继续猜 当用户刚好输入的就是这个随机数的时候 提示成功 并显示用户猜了多少次. 14. 老师问学生,这道题你会做了吗? 如果学生答"会了(y)",则可以放学. 如果学生不会做(n),则老师再讲一遍,再问学生是否会做了......直到学生会为止,才可以放学. 直到学生会或老师给他讲了10遍还不会,都要放学 15. 写1个程序. 随机的产生1个2位数的加法运算.让用户输入这个运算的结果 然后判断这个结果是否正确. 来10次. 每个人默认有10分. 产生10个加法运算.操作数的范围在0-100之间. 每产生1个加法运算 就让用户输入结果.判断是否正确. 当回答正确的时候就为用户加1分. 错误的时候就扣1分. 当10道题目回答完毕之后 就显示用户得的分数. ***
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值