约瑟夫置换(约瑟夫环问题)详解

博客探讨了一则17世纪的数学问题,涉及在30人中通过报数淘汰一半人,确保非教徒被剔除的策略。文章提供了两种编程实现方法:使用数组的循环处理和基于递归的简洁解决方案。通过循环数组,每当数到9时淘汰一人,直至剩余15人。递归方法则利用新环的编号推算旧环的出局者。这两种方法都巧妙地解决了问题。
摘要由CSDN通过智能技术生成

17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。

Ⅰ.数组

思路:

1.开一个数组,把每个人都放进去,每个人所在的数组位置都初始化为0.(一共n个人,数到m出去)。

2.定义cnt,表示目前已经出局的人数。

3.报数做一个循环,循环条件是cnt!=n。

#include<stdio.h>
int main()
{
    int n, m, i, count = 0, num = 0;
    int a[100]={0}; 
    scanf("%d\n%d", &n, &m);
    for (i = 1; i <= n; i++) {
        a[i] = i;
    }                                                     //存入编号
    for (i = 1; ; i++) {
        if (a[i] != 0) {
            num++;                                        // num记录已出局的人数
            if (num == m) {
                count++;
                if (count == n) {
                    break;
                }
                printf("No%d: %d\n", count, a[i]);
                a[i] = 0;
                num = 0;
            }                                             // 报数为 m 出圈:
                                             //出圈人数加一,输出编号,编号清零,计数器清零
        }
        if (i == n) {
            i = 0;
        }
    }
    printf("Last No is: %d", a[i]);
    return 0;
}

Ⅱ.递归实现(这个最简洁)

有n个人,报到数字k出局,第i个人出局的编号。

假如有10个人 报到3出局

第一个出局的ysf(10,3,1)=2;旧环第二个出局的ysf(10,3,2)=5;

新环第一个出局的ysf(9,3,1)=2,即旧环的第二个可以由新环的第一个+3推算而来。

ps:以防加的数超过总人数,给ysf%n即可。

#include<stdio.h>
int ysf(int n,int k,int i)         //n个人,报到k出去,第i个人的编号是
{
    if(i==1)
        return (n+k-1)%n;
    else
        return (ysf(n-1,k,i-1)+k)%n;   //防止编号越界
}
int main()                             //测试用例
{                        
    int k=3;
    int n;
    scanf("%d",&n);
    printf("%d",ysf(n,3,n)+1);
    return 0;
}

Ⅲ循环链表

这个俺不会,就是知道有这个方法。

等我学了再给兄弟萌哔哔~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xxx_xiyuyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值