第18 题: 题目:n 个数字(0,1,…,n-1)形成一个圆圈,从数字0 开始每次从这个圆圈中删除第m 个数字(第一个为当前数字本身,第二个为当前数字的下一个数 字)。

这篇博客讨论了Josephus问题的推广,即在n个数字形成的圆圈中,从数字1开始每次删除第m个数字,求解最后剩下的数字。文章介绍了利用《具体数学》中的知识来解决此类问题,并提供了算法实现,包括一个改进的算法来计算最后的幸存者位置。
部署运行你感兴趣的模型镜像
当一个数字删除后,从被删除数字的下一个继续删除第m 个数字。

求出在这个圆圈中剩下的最后一个数字。


思路:

      把这个题目中的开始数字改下以便下面的说明,n 个数字(1,…,n-1,n)形成一个圆圈,从数字1 开始每次从这个圆圈中删除  第(第说明与开始数字无关)m 个数字(第一个为当前数字本身,第二个为当前数字的下一个数 字)。

     这个是Josephus问题的推广(Josephus问题是m = 3)。

     这个题目出题人的意图应该是采用模拟的方法吧,这种方法网上很多。正好前段时间上了具体数学这门课,下面利用《具体数学》中提到的知识来解决这样的问题。可以参考具体数学第三章第三节。

    下面是对原文的一段摘抄:(Josephus问题是m = 3)

     每当一个人越过,我们就赋予一个新的数。于是,1和2变成了n+1和n+2,则3被执行;4和5变成n+3和n+4,则6被执行;……,3k+1和3k+2变成n+2k+1和n+2k+2,则3k+3被执行;……,则3n被执行(或留下幸存),例如当n=10,数是

          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

 数3k最后以消除第k个人而告终。所以如果我们能计算出人数3n的原先的数,则我们能断定谁是幸存者。

    若N>n,人数N一定要有一个以前的数,且我们能找到它。如下:我们有N=n+2k+1或N=n+2k+2,因此k= (int)((N-n-1)/2),以前的数分别是3k+1或3k+2,也就是说,它是3k+(N-n-2k)=k+N-n,因此我们能计算幸存者数J3(n)如下:

    N = 3n;

    while  N>n    do     N:=(int)  ((N-n-1)/2 ) + N -n;

   J3(n)  :=  N.

   利用D = 3n+1-N来替换N,我们可以得到改进的算法:

  D:=1;

  while  D <=  2n    do   D :=  ceil(   3*D/2 );//ceil是c中的取上整函数

   J3(n) :=  3n + 1 -D.

 同样的道理消除第m个人。

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
	double a = 1.0;
	int m = 0,n = 0;

	cin >> m >> n;

	while ( a <= (m-1)*n )
	{
		a = ceil ( m*a/(m-1) );
	}

	cout << (m*n + 1 - (int)a  - 1) << endl;//原文是从0开始,在此基础上-1.
	return 0;
}


     


您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 当前1 - 100项,共494项 第1页 Toggle Sidebar 7-73 n个小朋友分糖果 7-73 n个小朋友分糖果 分 15 作者 庄波 单位 山东航空学院 为了培养小朋友们分享的意识,老师教小朋友做分糖果的游戏,把自己带的糖果分给其他小朋友。 首先,全班 n 个小朋友围成一个圆圈,按排列顺序依次给他们编号 1,2,…,n。然后,从 1 号小朋友开始,将自己的糖果平均分成三份(如果有多余的糖果则立即吃掉),自己保留一份,其余两份分别分给与他相邻的两个小朋友。接下来按照编号顺序,2 号,3 号,4 号,…,直到 n 号小朋友都这样做。 问经过一轮分糖果游戏,每个小朋友手上分别有多少个糖果? 输入格式: 第一行为小朋友人 n,保证 3≤n≤30。 第二行为空格隔开的 n 个正整,依次表示游戏开始时按编号从 1 到 n 的顺序每个小朋友手上的糖果。 输出格式: 在一行中输出空格隔开的 n 个整,依次表示游戏结束时按编号从 1 到 n 的顺序每个小朋友手上的糖果。 输入样例: 3 3 3 3 输出样例: 3 2 1 代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB C (gcc) Selection deleted 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 #include<stdio.h> int main(){ int n; int a[30]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]);} //第一个分糖果量 a[0]=a[0]/3; a[n-1]+=a[0]; a[1]+=a[0]; //2到n-1的糖果量 for(int i=1;i<n-1;i++){ a[i]=a[i]/3; a[i-1]+=a[i]; a[i+1]+=a[i]; } //最后个分糖果量 a[n-1]=a[n-1]/3; a[n-2]+=a[n-1]; a[0]+=a[n-1]; printf(" "); printf("%d",a[i]); return 0; } 哪不对?
最新发布
10-14
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值