拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 C语言程序设计100例之(46):巧妙称重

C语言程序设计100例之(46):巧妙称重

白鹭 - 2022-02-12 2072 0 0

例46  巧妙称重

题目描述

有N个篮子,编号1~N,篮子中有很多金币,每个重w,但是有一个编号的篮子中,每个金币重d,现从第一个篮子中拿1个金币,第二个篮子中拿2个,…,第N-1中拿N-1个,第N中不拿,给出这些金币的总重量wei,问:是第几个篮子中的金币重量较轻?

输入格式

输入档案将由一行或多行组成;每行包含四个正整数,由一个空格分隔,前三个整数分别是数字N、w和d,如上所述,第四个整数是所选硬币称重的结果,

N至少为2,但不超过8000,w的值最多为30,d的值将小于w,

输出格式

对于每组测验资料输出一行,由一个正整阵列成:装有比其他篮子中金币轻的金币的篮子编号,

输入样例

10 25 8 1109

10 25 8 1045

8000 30 12 959879400

输出样例

2

10

50

        (1)编程思路,

        这是一道数学题分析题,若设1~N-1这N-1个篮子中放的金币均为重量为w的金币,则应有的总重量为:w*(1+n-1)*(n-1)/2(简单的等自变量列求和),所求的和减去实际称出的重量wei,得到金币重量的差值sum = ((n-1)*(n-1+1)/2)*w-wei,若sum为0,则装有重量为d的篮子编号必为N;若sum不为0,除以d,得到较轻金币的个数,即为所求编号,

(2)源程序,

#include <stdio.h>

int main()

{

     int n,w,d,p;

     while (scanf("%d%d%d%d",&n,&w,&d,&p)!=EOF)

     {

         int sum = ((n-1)*(n-1+1)/2)*w-p;

         if(sum==0)

             printf("%d\n",n);

         else

             printf("%d\n",sum/d);

     }

     return 0;

}

习题46

46-1  鬼谷子的钱袋

        本题选自洛谷题库 (https://www.luogu.org/problem/P2320)

题目描述

鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各诸侯车的特派员前来向他咨询时政,

有一天,他在咸阳游历的时候,朋友告诉他在咸阳最大的拍卖行(聚宝商行)将要举行一场拍卖会,其中有一件宝物引起了他极大的兴趣,那就是无字天书,

但是,他的行程安排得很满,他已经买好了去邯郸的长途马车票,不巧的是出发时间是在拍卖会快要结束的时候,于是,他决定事先做好准备,将自己的金币数好并用一个个的小钱袋装好,以便在他现有金币的支付能力下,任何数目的金币他都能用这些封闭好的小钱的组合来付账,

鬼谷子也是一个非常节俭的人,他想方设法使自己在满足上述要求的前提下,所用的钱袋数最少,并且没有两个钱袋装有相同的大于1的金币数,假设他有m个金币,你能猜到他会用多少个钱袋,并且每个钱袋装多少个金币吗?

输入格式

包含一个整数,表示鬼谷子现有的总的金币数目m,其中,1≤m ≤1000000000,

输出格式

两行,第一行一个整数h,表示所用钱袋个数

第二行表示每个钱袋所装的金币个数,由小到大输出,空格隔开

输入样例

3

输出样例

2

1 2

       (1)编程思路,

先看看金币数目m为1~10怎么表示,

m=1,显然1个钱袋,装1个金币;m=2,用2个钱袋,各装1个金币;

m=3,用2个钱袋,分别装1个和2个金币;

m=4,用3个钱袋,分别装1个、1个和2个金币;

m=5,用3个钱袋,分别装1个、1个和3个金币;

m=6,用3个钱袋,分别装1个、2个和3个金币;

m=7,用3个钱袋,分别装1个、2个和4个金币;

m=8,用4个钱袋,分别装1个、1个、2个和4个金币;

m=9,用4个钱袋,分别装1个、1个、2个和5个金币;

m=10,用4个钱袋,分别装1个、1个、3个和5个金币;

……

        由上面规律可以看出,n以内的任何数字可以用1到n/2以内的数字表示,n/2以内的任何数字可以用1到n/4以内的数字表示,……,

        例如,为了表示15,一个袋子装(15+1)/2=8个金币,剩下7个金币;为了表示7,用一个袋子装(7+1)/2=4个金币,剩下3个金币;为了表示3,用一个袋子装(3+1)/2=2个金币,剩下2个金币,可用两个袋子,各装1个金币,即m=15,用4个钱袋,分别装1个、2个、4个金币和8个金币;

        M=29时,一个袋子装(29+1)/2=15个金币,剩下14个金币用4个袋子,分别装1个、2个、4个金币和7个金币,

        M=30时,一个袋子装(30+1)/2=15个金币,剩下15个金币用4个袋子,分别装1个、2个、4个金币和8个金币,

        M=31时,一个袋子装(31+1)/2=16个金币,剩下15个金币用4个袋子,分别装1个、2个、4个金币和8个金币,

        ……

       (2)源程序,

#include <stdio.h>

int main()

{

    int a[32];

    int n;

    scanf("%d",&n);

    int cnt=0;

    while (n>0)

    {

        a[cnt++]=(n+1)/2;

        n=n/2;

    }

    printf("%d\n",cnt);

    for (int i=cnt-1;i>=0;i--)

        printf("%d ",a[i]);

    printf("\n");

    return 0;

}

46-2  圆桌会议

题目描述

N个哲学家围坐在一张圆形的桌子旁进行交流,在一天在讨论的时候,哲学家Eddy想出了一个极为古怪的想法,如果他们在每一分钟内,一对相邻的两个哲学家交换一下位子,那么要多少时间才能得到与原始状态相反的座位顺序呢?

输入格式

对于给定数目N(1<=N<=32767),表示有N个哲学家,求要多少时间才能得到与原始状态相反的座位顺序,即对于每个人,原先在他左边的人后来在他右边,原先在他右边的人在他左边,

输出格式

对每个资料输出一行,表示需要的时间(以分钟为单位),

输入样例

4

5

6

输出样例

2

4

6

       (1)编程思路,

        若n个哲学家坐成一排,123…n逆序变为n…321,需要交换位置1+2+…+(n-1)=n*(n-1)/2次,即1右移n-1步,2右移n-2步,……,

       现在n个哲学家在圆桌边围成一圈,所以可以双向移动,因而可将n分成两部分,n/2和n-n/2,两部分分别按一排独自逆序,可以达到时间最少,

       例如1234,可分成12和34,2分钟后可得到2143,由于成圈,所以也是逆序,

       再如12345,可分成123和45,123逆序为321用2分钟,45逆序为54用1分钟,3分钟后可得到32154,由于成圈,所以也是逆序,

      (2)源程序,

#include <stdio.h>

int main()

{

    int n;

    while(scanf("%d",&n)!=EOF)

    {

        int a=n/2;

        int b=n-a;

        printf("%d\n",a*(a-1)/2+b*(b-1)/2);

    }

    return 0;

}

46-3  取木棍

题目描述

有边长分别为1~n的n根小木棍,现在要求拿走尽量少的小木棍,使得剩下的小木棍任意取三根都不能组成三角形,

输入格式

输入第一行包含一个整数T(T≤20),表示测验用例的数量,

对于每个测验用例,只有一行描述给定的整数n(1≤N≤20),

输出格式

对于每个测验用例,输出一行“case#x:y”,其中x是用例编号(从1开始),y是应取走的最小木棍数目,

输入样例

3

4

5

6

输出样例

Case #1: 1

Case #2: 1

Case #3: 2

        (1)编程思路,

        边长为1~n的n根小木棍取走一些后,若最后剩下的小木棍的边长构成Fib(斐波那契)数列,则一定可以保证任意三根木棍都不能组成三角形,

      (2)源程序,

#include <stdio.h>

int main()

{

    int a[22]={0};

    a[1]=a[2]=a[3]=a[5]=a[8]=a[13]=a[21]=1;

    int i;

    for (i=2;i<22;i++)

        a[i]+=a[i-1];

    int t;

    scanf("%d",&t);

    for (i=1; i<=t; i++){

        int n;

        scanf("%d",&n);

        printf("Case #%d: %d\n", i,n-a[n]);

    }

    return 0;

}

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *