本周是习题时间
1.凑硬币:输入一个10元以内的面额,输出所有用一角,两角和五角能组合出的结果
版本一:以角为单位,从低到高进行循环嵌套
#include<stdio.h>
int main()
{
int x;
printf("请输入一个十元以下的面额(以角为单位):");
scanf_s("%d", &x);
int one=0, two=0, five=0;
for (one = 1; one <x; one++) {
if (one + two * 2 + five * 5 == x) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
}
for (two = 1; two < x / 2; two++) {
if (one + two * 2 + five * 5 == x) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
}
for (five = 1; five < x / 5; five++) {
if (one + two * 2 + five * 5 == x) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
}
}
}
}
return 0;
}
很明显,前面两个If都不能起作用,因为即便可能没有进入后两个循环,two和five 依旧会被重新赋值为1。而且这样做得到的结果只能是部分的。
版本二:以元为单位,从低到高
#include<stdio.h>
int main()
{
double x;
printf("请输入一个十元以下的面额(以元为单位):");
scanf_s("%lf", &x);
int one , two , five ;
for (one = 1; one < x * 10; one++) {
for (two = 1; two < x * 10 / 2; two++) {
for (five = 1; five < x * 10 / 5; five++) {
if (one + two * 2 + five * 5 == x * 10) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
}
}
}
}
return 0;
和版本一相似,只是少了多余的两个if语句且使用了浮点型
版本三:从低到高,多for多If
#include<stdio.h>
int main()
{
int x;
int one, two, five;
int isprime = 1, a = 1,b=1,c=1;
printf("请输入一个10元一下的面额(以角为单位):");
scanf_s("%d", &x);
for (one = 1; one <= x; one++) {
if (one == x) {
printf("%d个一角\n",one);
}
for (two = 1; two <= x / 2; two++) {
if (one + two * 2 == x) {
printf("%d个一角,%d个两角\n", one, two);
}
if (two * 2 == x) {
if (isprime==1) {
printf("%d个两角\n", two);
isprime = 0;
}
}
for (five = 1; five <= x / 5; five++) {
if (five * 5 + two * 2 + one == x) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
}
if (five * 5 == x) {
if (a==1) {
printf("%d个五角\n", five);
a = 0;
}
}
if (five * 5 + two * 2 == x) {
if (b == 1) {
printf("%d个两角,%d个五角\n", two, five);
b = 0;
}
}
if (five * 5 + one == x) {
if (c == 1) {
printf("%d个一角,%d个五角\n", one, five);
c = 0;
}
}
}
}
}
return 0;
}
解决了前两段代码只能输出部分组合的弊端,但是它实在是太冗长了!
版本四:从高到低,最简洁有效!
#include<stdio.h>
int main()
{
double x;
printf("请输入一个十元以下的面额(以元为单位):");
scanf_s("%lf", &x);
int one, two, five;
for (five = 0;five <= x* 10/5; five++) {
for (two = 0; two <= x *10/2; two++) {
for (one= 0; one <= x*10 ; one++) {
if (one + two * 2 + five * 5 == x*10) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
}
}
}
}
return 0;
}
换了一种思路,即由低到高对循环进行排序。关键在于它把初始值全部换成了0,这样保证了直接进入里面循环的可能,从而让每种组合从以全部为一角的情况为伊始,逐渐增加两角和五角的组合。达到事半功倍的效果。
版本五:接力break
int main()
{
int x;
printf("请输入一个十元以下的面额(以元为单位):");
scanf_s("%d", &x);
int one, two, five;
int exit = 0;
for (one = 1; one < x * 10; one++) {
for (two = 1; two < x * 10 / 2; two++) {
for (five = 1; five < x * 10 / 5; five++) {
if (one + two * 2 + five * 5 == x * 10) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
exit = 1;
}
}
if (exit == 1) break;
}
if (exit)break;
}
return 0;
}
这是以版本二为基础进行的改造,目的是使得到一组解以后就能够脱离循环。
版本六:goto——
用一种新的表现形式去替代接力break的形式:
#include<stdio.h>
int main()
{
int x;
printf("请输入一个十元以下的面额(以元为单位):");
scanf_s("%d", &x);
int one, two, five;
for (one = 1; one < x * 10; one++) {
for (two = 1; two < x * 10 / 2; two++) {
for (five = 1; five < x * 10 / 5; five++) {
if (one + two * 2 + five * 5 == x * 10) {
printf("%d个一角,%d个两角,%d个五角\n", one, two, five);
goto out;
}
}
}
}
out:
return 0;
}
2.整数的正序输出
版本一:超复杂
#include<stdio.h>
int main()
{
int x, a = 0, b = 0;
int count = 0, m = 0,n = 0, i = 0, mask = 1, isprime = 1;
printf("请输入一个正整数:");
scanf_s("%d", &x);
int t = x, y = x;
while (t > 0) {
count++;
if (t > 9) {
mask *= 10;
}
t /= 10;
}
for (; mask > 0; mask /= 10) {
count--;
if (x % mask == 0) {
isprime = 0;
break;
}
}
while (y > 0) {
a = y % 10;
m = m * 10 + a;
y /= 10;
}//倒序重排得到新的数
if(isprime == 1) {
while (m > 0) {
b = m % 10;
printf("%d ", b);
m /= 10;
}//得到末尾无0的情况
}
if(isprime==0) {
while (m > 0) {
b = m % 10;
printf("%d ", b);
m /= 10;
}
for (; count > 0;count--) {
printf("0 ");
}//得到末尾有0的情况
}
return 0;
}
版本二:简洁
#include<stdio.h>
int main()
{
int x;
scanf_s("%d", &x);
int mask = 1;
int t = x;
while (t > 9) {
t /= 10;
mask *= 10;
}
do {
int d = x / mask;
printf("%d", d);
if (mask > 9) {
printf(" ");
}
x %= mask;
mask /= 10;
} while (mask > 0);
return 0;
}
3.求最大公约数
版本一:
int main()
{
int a, b;
int c = 0;
printf("请输入两个正整数或零,求它们的最大公约数:");
scanf_s("%d %d", &a, &b);
for(int i=1;i<=a;i++){
if (a% i == 0) {
if (b % i == 0) {
c = i;
}
}
}printf("最大公约数为:%d", c);
return 0;
版本二:辗转相除法
#include<stdio.h>
int main()
{
int a, b,c=1;
printf("请输入两个自然数:");
scanf_s("%d %d", &a, &b);
if (a == 0) {
printf("最大公约数为:%d", b);
}
else if (b == 0) {
printf("最大公约数为:%d", a);
}
else {
while (a % b != 0) {
c = a % b;
a = b;
b = c;
}
printf("最大公约数为:%d", c);
}
return 0;
}
5.数列求和
其一:
#include<stdio.h>
int main()
{
int n;
double sum = 0;
printf("请输入一个正整数:");
scanf_s("%d", &n);
for (int i = 1; i <= n; i++) {
sum += 1.0 / i;
}
printf("f(n)=%f", sum);
return 0;
}
其二:
#include<stdio.h>
int main()
{
printf("%d\n", 1 % 2);//结果为1
printf("%f\n", 1 % 2);//结果为0
printf("%f\n", 1 / 2);//结果为0
printf("%d\n", 1.0 / 2);//结果为0
printf("%f\n", 1.0 / 2);//结果为0.5
int n;
double sum = 0,sign=1;
printf("请输入一个正整数:");
scanf_s("%d", &n);
for (int i = 1; i <= n; i++) {
//if (n % 2 == 0)
//sum -= 1.0 / i;
sum +=sign / i;
sign = -sign;
//else
//sum += 1.0 / i;
}
printf("f(n)=%f", sum);
return 0;
}