2.5 循环结构程序设计 习题

习题 2-1

  打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。

  例如:153是一个“水仙花数”,因为153=13+53+33

程序 2-1

#include<stdio.h>
int main()
{
    int i = 100;
    while (i < 1000)
    {
        int A = i /100;
        int B = i / 10 % 10;
        int C = i % 10;
        if (i == A * A * A + B * B * B + C * C *C)
            printf("%d\n", i);

        i++;
    }

    return 0;
}

 

习题2-2 韩信点兵

  相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排,五人一排,七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入包含多组数据,每组数据包含3个非负整数a,b,c, 表示每种队形排尾人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。输入到文件结束为止。

【分析】第一种方法直接暴力求解,最容易想到。第二种方法是我在搜索资料时发现的,顺便就学了并用代码实现了下。

程序 2-2 (a)

#include<stdio.h>
int main()
{
    int a, b, c, kase = 0;
    while(scanf("%d %d %d", &a, &b, &c) == 3);
    {
        for (int i = 10; i <= 100; i++)
        {
              //直接判断 i 是否满足条件
            if (i % 3 == a && i % 5 == b && i % 7 == c)
            {
                printf("Case %d : %d \n", ++kase, i);
                break;
            }

            if (i == 100)
            {
                printf("Case %d : No answer \n", ++kase);
                break;
            }
        }
    }

    return 0;
}

  算法简单的使用了中国剩余定理。

  接下来是直接贴有关知识点。

  

一般地有如下定义

定义   对于整数 a 、b及自然数 n ,如有

a = n q1 + r1 ,(r1 <n)

b = n q2 + r2 , (r2 <n) 并且r1= r2

则称a与b对于模n同余,记作a≡b(mod n )上式叫做同余式。

还需要下面两个定理

定理1  如a被n除所得的余数等b被n除所得的余数,c被n除所得的余数等于d被n除所得的余数, 则ac被n除所得的余数等于b d被n除所得的余数。

用同余式叙述就是:

如a≡b(mod n ),c≡d(mod n )

则ac≡b d(mod n )

定理2  被除数a加上或减去除数b的倍数,再除以b,余数r不变。即

如a ≡ r(mod b ),则a ± b n≡r(mod b )

例如70≡1(mod 3 )可得70±10×3≡1(mod 3 )

例如:一个数除以3余2,除以5余3,除以7余2,求适合条件的最小的自然数χ。

解:由题意可得同余式组

Χ≡2(mod 3 )

Χ≡3(mod 5 )

Χ≡2(mod 7)

解:[ 5,7]=35,35≡2(mod 3 ),35为5与7的倍数,且被3除余2

[ 3,7]=21,21≡1(mod 5),又3≡3(mod 5),由定理1 得,

21×3≡1×3(mod 5 ),即63≡3(mod 5 ),63为3yu7的倍数,且被5除余3

[ 3,5]=15,15≡1(mod 7),又2≡2(mod 7),由定理1 得,

15×2≡1×2(mod7 ),即30≡2(mod 7),30为3与5的倍数,且被7除余2

35+63+30=128  由定理2 知

128≡2(mod3)

128≡3(mod 5)

128≡2(mod 7)

128适合题中条件但不是最小的数

又∵[3,5, 7]=105

∴128 -105=23

由定理2 知,23仍适合条件且是最小的自然数。

 

※      ※      ※      ※       ※       ※       ※ 

例如:一个数除以5余4,除以7余2,除以11余8,求适合条件的最小的自然数χ。

解:由题意可得同余式组

Χ≡4(mod 5 )

Χ≡2(mod 7 )

Χ≡8(mod 11)

[ 7,11]=77,77≡2(mod 5 )又2≡2(mod 5 ),由定理1 得,

77×2≡2×2(mod 5 ),即154≡4(mod 5 )

154为7与11的倍数,且被5除余4

[ 5,11]=55,55≡6(mod 7 ),又5≡5(mod 7 ),由定理1 得,

55×5≡6×5(mod 7),275≡30(mod 7),

275为5与11的倍数,且被7除余2

[ 5,7]=35,35≡2(mod 11 ),又4≡2(mod 11 ),由定理1 得,

35×4≡2×4(mod 11 ),即140≡8(mod 11 )

140为5与7的倍数,且被11除余8

154+275+140=569 由定理2 知

569≡4(mod 5 )

569≡2(mod 7 )

569≡8(mod 11)

569适合题中条件但不是最小的数

又∵[5, 7,11]=385

∴569 -385=184

 

代码实现如下:

 程序 2-2 (b)

#include<stdio.h>
int main()
{
      //分别找出能被两个数整除,而满足被第三个整除余一的最小的数
      int a, b, c, total, kase = 0;
      while (scanf("%d%d%d",&a, &b, &c) == 3)
      {
            int A = 0, B = 0, C = 0;
            //首先要满足能被两个数整除
            A = 5 * 7;
            //然后要满足能被第三个数除余且值为相对应的a,b,c
            //若不满足,根据定理一进行相乘处理
            if (A % 3 != a)
            {
                  A = A * a;
            }

            B = 3 * 7;
            if (B % 5 != b)
            {
                  B = B *b;
            }

            C = 3 * 5;
            if (C % 7 != c)
            {
                  C = C * c;
            }
            //得出一个初步值
            total = A + B + C;
            //初步值不一定是满足条件的最小值,若比公倍数大则要减去公倍数
            if (total > 105)
            {
                  total -= 105;
            }
            //最后进行验算,并判断是不是在条件区间内
            if (total % 3 == a && total % 5 == b && total % 7 == c && total > 10 && total < 100)
            {
                  printf("Case %d : %d\n", ++kase, total);

            }
            else
            {
                  printf("Case %d : No answer", ++kase);
            }

      }
      return 0;
}

 

 

习题 2-3 输入正整数 n <= 20, 输出一个n层的倒三角形。

  没难度直接上代码

程序 2-3

#include<stdio.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int space = i -1;
        for (int j = 0; j < space; j++)
            printf(" ");
        int jinhao = 2 * n - 2 * i +1;
        for (int k = 0; k < jinhao; k++)
            printf("#");

        printf("\n");
}    }

 

 

习题 2-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 2 : 0.00001

程序 2-4

#include<stdio.h>
int main()
{
      int n, m;
      int kase = 0;
      double sum= 0;
      while(scanf("%d %d", &n, &m) == 2 && n)
      {
           sum = 0;
            for (int i =n; i <= m; i++)
                  {
                        long temp = i * i;;
                        sum +=  1.0 / temp;
                  }

                  printf("Case %d : %.6f\n", ++kase, sum);
      }
}

  本题有陷阱,数字太大乘法会溢出,观察发现1 / 100002对结果影响很小了,可以考虑定一个界限,再大的值定为0;

 

 

习题 2-5 分数化小数

  输入正整数a,b,c, 输出 a/b的小数形式,精确到小数点 c 位。 a,b <= 10,   c <= 100。输入包含多组数据,结束标记为 a = b = c = 0;

  样例输入:

    1 6 4

    0 0 0

程序 2-5

#include<stdio.h>
int main()
{
      int a, b, c, kase = 0;
      while(scanf("%d%d%d", &a, &b, &c) == 3 && a)
      {
            double decimal = a * 1.0 / b;
            //注意通配符 * 号和取代 * 号的 c 的顺序
            printf("Case %d : %.*f\n", ++kase, c, decimal);
      }

      return 0;
}
    

 

 

习题2-6 排列

  用1, 2, 3 ……9组成的3个三位数字 abc,def,ghi,每个数字恰好使用一次,要求 abc:def:ghi = 1:2:3。按照“abc def ghi ”的格式输出所有解,每行一个解。

【分析】有两个难点。

  1.每个数字只用一次。

  2.abc:def:ghi = 1:2:3

程序2-6

#include<stdio.h>
int main()
{
      //只需给出 abc 就可以通过 *2, *3得到def,ghi
      //abc 最小为 123
      int abc = 123;
      //abc最大值为329,应为 abc*3最大为987
      for (abc; abc <= 329; abc++)
      {
            int a,b,c,def,d,e,f,ghi,g,h,i,sum,mul;
            a = abc / 100;
            b = abc / 10 % 10;
            c = abc % 10;

            def = abc * 2;
            d = def / 100;
            e = def / 10 % 10;
            f = def % 10;

            ghi = abc * 3;
            g = ghi / 100;
            h = ghi / 10 % 10;
            i = ghi % 10;
            
            //将每个数的每位值分别相加,相乘
            sum = a + b + c + d + e + f + g + h +i;
            mul = a *b * c * d * e * f * g * h * i;
            //因为每个数字只用一次,所以他们的和始终为 45 ,积始终为 362880
            if (sum == 45 && mul == 362880)
                  printf("%d %d %d\n", abc, def, ghi);
      }

      return 0;
}

 

posted @ 2015-07-10 10:58  Traim304  阅读(1034)  评论(0编辑  收藏  举报