【算法】算法中的趣味数学(一)

简介:

小续

   以下是我收集的一些有趣的计算实例,希望能够提高读者的编程水平及分析问题/解决问题的能力

---------------------------------------------


马克思手稿中的数学题

  马克思手稿中有一道趣味数学题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭共花了50先令。若每个男人花3先令,每个女人花2先令,每个小孩花1先令。问男人、女人和小孩各有几人?

   实例解析:

   设x,y,z分别代表男人、女人和小孩的人数。按题目要求,可得到下面方程:

                  x + y + z = 30                (1)

                  3x + 2y + z = 50              (2)

   (2)-(1)可得

                  2x + y = 20                  (3)

   由(3)式可知,x的变化范围是1~10 (根据题意,男人、女人、小孩都有,故x、y、z都不能为0)。  

    程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int  main()
{
     int  x,y,z,count = 0;
     clrscr();
     puts ( " >> The solutions are:" );
     printf ( "  No.      Men     Women   Children\n" );
     printf ( "--------------------------------\n" );
     for (x = 1; x <= 10; x++)
     {
         y = 20 - 2*x;                    //由(3)式求y
         z = 30 – x - y;                 //由(1)式求z
         if (3*x + 2*y + z == 50 && y && z)  //当前组合是否满足式(2)
         printf ( " <%2d> | %2d | %2d | %2d\n" , ++count,x,y,z);
     }
     printf ( "--------------------------------\n" );
     printf ( " Press any key to quit..." );
     getch();
     return  0;
}





配对新郎和新娘

  3对情侣参加婚礼,3个新郎为A、B、C,3个新娘为X、Y、Z。有人不知道谁和谁结婚,于是询问了6位新人中的3位,但听到的回答是这样的:A说他将和X结婚;X说她的未婚夫是C;C说他将和Z结婚。这人听后知道他们在开玩笑,全是假话。请编程确认谁和谁是一对。

  实例解析:

  分表将A、B、C用1,2,3表示,将X和A结婚表示为“X == 1”,将Y不与A结婚表示为“Y !=1”,按题目叙述可写出下列表达式:

        X != 1           A不与X结婚

        X != 3           X的未婚夫不是C

        Z != 3           C不与Z结婚

  穷举满足以上条件所有可能的情况。

  程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int  main()
{
     int  x,y,z;
     puts ( " >> The solutions are:" );
     printf ( "-------------------------------------\n" );
     for (x = 1; x <= 3; x++)           //穷举x的全部可能配偶
         for (y = 1; y <= 3; y++)         //穷举y的全部可能配偶
             for (z = 1; z <= 3; z++)       //穷举z的全部可能配偶
                 if (x!=1 && x!=3 && z!=3 && x!=y && x!=z && y!=z)
                 {
                     printf ( "X will marry to %c.\n" 'A' +x-1);
                     printf ( "Y will marry to %c.\n" 'A' +y-1);
                     printf ( "Z will marry to %c.\n" 'A' +z-1);
                 }
     printf ( "--------------------------------------\n" );
     printf ( " Press any key to quit..." );
     getch();
     return  0;
}





分糖果

  10个小孩围成一圈分糖果,老师分给第一个小孩10块,第二个小孩2块,第三个小孩8块,第四个小孩22块,第五个小孩16块,第六个小孩4块,第七个小孩10块,第八个小孩6块,第九个小孩14块,第十个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩,糖块为奇数的可向老师再要一块。问这样的操作经过几次,大家手中的糖一样多?每人有多少块糖?

  实例解析:

  分糖过程是一个机械的重复过程。算法完全可以按照描述的过程进行模拟。

  程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
void  print( int  s[]);
int  judge( int  c[]);
int  j = 0;
int  main()
{
     int  sweet[10] = {10,2,8,22,16,4,10,6,14,20};
     int  i, t[10], k;
     printf ( "Child No.  1   2  3  4  5  6  7  8  9  10\n" );
     printf ( "-------------------------------------\n" );
     printf ( "Round No.|\n" );
     print(sweet);                //输出每个人手中糖的块数
     while (judge(sweet))
     {       //若不满足要求则继续进行循环
         for (i = 0; i < 10; i++)
             t[i] = sweet[i] = sweet[i]/2;  //每个人手中的糖分成两半
         for (k = 0; k < 9; k++)
         {
             sweet[k+1] = sweet[k+1] + t[k];  //分出的一半糖给右边
             if (sweet[k+1]%2!=0)
                 sweet[k+1]++;
         }
         sweet[0] += t[9];
         if (sweet[0]%2!=0)
             sweet[0]++;
         print(sweet);              //输出当前每个孩子中手中的糖数
     }
     printf ( "-------------------------------------\n" );
     printf ( "\n Press any key to quit..." );
     getch();
     return  0;
}
int  judge( int  c[])
{
     int  i;
     for (i = 0; i < 10; i++)    //判断每个孩子手中的糖是否相同
     if (c[0] != c[i])
             return  1;           //不相同返回 1
     return  0;
}
  
void  print( int  s[])       //输出数组中每个元素的值
{
     int  k;
     printf ( "      <%2d> | " , j++);
     for (k = 0; k < 10; k++)
         printf ( "%4d" , s[k]);
     printf ( "\n" );
}





波瓦松的分酒问题

  法国著名数学家波瓦松(Poison)在青年时代研究过一个有趣的数学问题:某人有12品脱的啤酒一瓶,想从中倒出6品脱,但他没有6品脱的容器,仅有一个8品脱和5品脱的容器,怎样才能将啤酒分成两个6品脱呢?

  实例解析:

  将12品脱酒用8品脱和5品脱的空瓶平分,可以抽象为解不定方程:

               8x - 5y = 6

  其意义是:从12品脱的瓶中向8品脱的瓶中倒x次,并且将5品脱瓶中的酒向12品脱的瓶中倒y次,最后在12品脱的瓶中剩余6品脱的酒。

  分别用a,b,c代表12品脱、8品脱和5品脱的瓶子,求出不定方程的整数解,按照不定方程的意义则倒酒法为:

      a→b→c→a

       x     y

  倒酒的规则如下:

  (1)按a→b→c→a的顺序;

  (2) b倒空后才能从a中取;

  (3) c装满后才能向a中倒。


  程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
void  getti( int  a,  int  y,  int  z);
int  i;            //最后需要分出的重量
int  main()
{
     int  a, y, z;
     printf ( ">>Input Full bottle a,Empty y,z, and Get volumes i:\n" );
     //a第一个瓶的容量  y:第二个瓶的容量  z:第三个瓶的容量
     printf ( " >> " );
     scanf ( "%d%d%d%d" , &a, &y, &z, &i);
     getti(a, y, z);            //按a -> y -> z -> a的操作步骤
     printf ( "\n Press any key to quit..." );
     getch();
     return  0;
}
void  getti( int  a,  int  y,  int  z)
//a:第一瓶的容量  y:第二个瓶的容量 z:第三个瓶的容量
{
     int  b = 0, c = 0, j = 0;   // b:第二瓶酒重  c:第三瓶酒重 j: 步数
     puts ( " >> The division steps are as follows.\n" );
     printf ( " Bottle:    a<%d> b<%d> c<%d>\n" ,a,y,z);
     printf ( "-----------------------------\n" );
     printf ( " Step No.|\n" );
     printf ( "   <%d>   | %4d %4d %4d\n" ,j++,a,b,c);
     while (a!=i && b!=i && c!=i )
     //当三个瓶的酒都!=i
         if (!b)
         {            //如果第二瓶为空,则从第一瓶倒入第二瓶
             a -= y;
              b = y;
         }
         else  if (c == z)
         {      //如果第三瓶满,则将第三瓶倒入第一瓶中
             a += z;
             c = 0;
         }
         else   if (b > z-c)
         {   //如果第二瓶的酒>第三瓶的剩余空间
             b -= (z-c);   //由第二瓶倒满第三瓶,第二瓶保留剩余部分
             c = z;
         }
         else
         {           //将第二瓶全部倒入第三瓶中
             c += b;
             b = 0;
         }
         printf ( "   <%d>   | %4d %4d %4d\n" ,j++,a,b,c);
     }
     printf ( "-----------------------------\n" );
}




本文转自infohacker 51CTO博客,原文链接:http://blog.51cto.com/liucw/1171360


相关文章
|
2月前
|
自然语言处理 算法 数据处理
什么是算法
什么是算法
21 0
|
3月前
|
算法 C++ 容器
【C++11新算法】all_of、any_of、none_of算法
【C++11新算法】all_of、any_of、none_of算法
|
8月前
|
存储 并行计算 算法
FlashAttention算法详解
这篇文章的目的是详细的解释Flash Attention,为什么要解释FlashAttention呢?因为FlashAttention 是一种重新排序注意力计算的算法,它无需任何近似即可加速注意力计算并减少内存占用。所以作为目前LLM的模型加速它是一个非常好的解决方案,本文介绍经典的V1版本,最新的V2做了其他优化我们这里暂时不介绍。因为V1版的FlashAttention号称可以提速5-10倍,所以我们来研究一下它到底是怎么实现的。
384 0
|
算法
蚂群算法
蚂群算法
70 0
蚂群算法
|
存储 算法 测试技术
《算法》世界
一.什么是算法 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。一个算法必须具有:有穷性、确切性、输入项、输出项、可行性五个性质。
172 0
《算法》世界
拓展欧几里得算法
拓展欧几里得算法
57 0
|
算法
A*算法之在U3d下实现简单的自动寻路
算法简介: A搜寻算法俗称A星算法。A算法是比较流行的启发式搜索算法之一,被广泛应用于路径优化领域[。它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价该节点处于最短路线上的可能性的量度。
1237 0
|
算法
算法技巧总结
算法技巧总结
1351 0
|
算法 C语言
算法之【大整数乘法】
前面介绍了大整数的加减法,这次是大整数的乘法。同样是模拟竖式计算,但乘法运算需要克服一些技巧上的障碍:首先需要循环嵌套循环,然后通过一个数组实现逐位累加,最后统一完成进位工作。
935 0