利用C语言编程从数学角度揭秘2024春晚刘谦魔术《守岁共此时》

news2024/11/30 2:32:16

目录

一、魔术《守岁共此时》的步骤

二、揭秘魔术《守岁共此时》

三、数学模型约瑟夫问题(约瑟夫环)

四、编程复现魔术《守岁共此时》

五、程序运行结果


一、魔术《守岁共此时》的步骤

在今年的春晚里,魔术师刘谦表演了一个和纸牌相关的魔术,其精妙的设计带给观众极高的参与感,今天将从数学的角度感受这一魔术的魅力。刘谦在 2024 年春晚表演的魔术《守岁共此时》的全过程如下所示:

首先打乱四张牌,将四张牌对半分开把其中一半放在另一半下面,然后根据你名字长放对应的牌数到牌底,然后最上面三张牌插在剩下牌中间,位置可以任意但是必须在中间(即不能放在最上面或最下面),然后第一张牌就是我们要和最后牌比对的牌,之后以剩下牌继续,根据你是南方北方或者什么人来输入对应数字,拿对应的牌数放在剩下的牌中间,然后根据男女性别扔掉几张牌,然后上方牌放最下面重复7次,最后一步,最上面牌往下放一张再丢一张,以此重复,最后那张就和之前那张对应。

详细分解后的步骤如下所示:

①任意选四张牌,并把牌洗混。

②把扑克牌对折后撕开,让一堆放在另一堆上面,合并成8张牌。

③名字有几个字就把扑克牌从上面往下挪动几张。

④拿出最上面的三张牌,插入剩下牌的中间(位置随意)。

⑤把最上面的牌拿走放在口袋里。

⑥按照南北方人拿出不同的数量插入中间(南1北2不知道3)。

⑦按性别分别丢弃最上面的牌(男1女2)。

⑧嘴里喊出“见证奇迹的时刻”,每喊一个字,把一张牌从上面拿到最下面。

⑨“好运留下来,烦恼丢出去”,当喊出“好运留下来”时,把最上面的牌拿到最底下;当喊出“烦恼丢出去”时,把最上面的牌丢出去(扔掉),重复步骤直至仅剩一张牌。

⑩如果你步骤正确的话,剩余的半张牌和放在口袋里的半张牌会正好拼成一张牌。

二、揭秘魔术《守岁共此时》

三、数学模型约瑟夫问题(约瑟夫环)

在刘谦的魔术中,约瑟夫问题的核心思想被巧妙地应用于控制过程的结果。约瑟夫问题是通过固定间隔来选择和排除序列中的对象,直到只剩一个对象。在这个魔术中,尽管没有直接使用固定间隔的排除方法,但通过一系列精心设计的操作步骤(如牌的折叠、插入、丢弃等),实现了类似的控制效果,即无论参与者如何执行这些步骤,都会以一种预定的方式减少牌的数量,最终留下一张特定的牌。

据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决。Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

为了讨论方便,先把问题稍微改变一下,并不影响原意。问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求:胜利者的编号。

我们知道第一个人(编号一定是(m-1)mod n)出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m mod n的人开始):k,k+1,k+2, ... ,n-2,n-1,0,1,2,... ,k-2,并且从k开始报0,我们把他们的编号做一下转换:k -->0, k+1 -->1,k+2 -->2,...,k-2 -->n-2。

变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗。变回去的公式很简单,相信大家都可以推出来:x'=(x+k) mod n。

如何知道(n-1)个人报数的问题的解?只要知道(n-2)个人的解就行了。(n-2)个人的解呢?当然是先求(n-3)的情况 ,这显然就是一个倒推问题。

思路出来了,下面写递推公式:令 f 表示 i 个人玩游戏报 m 退出最后胜利者的编号,最后的结果自然是 f[n]。递推公式:f[1]=0,f[i]=(f[i-1]+m) mod i,且(i>1)。

根据该数学原理可以将类似的游戏改编成数学题目,比如下面这道改编题目:

四、编程复现魔术《守岁共此时》

#define _CRT_SECURE_NO_WARNINGS 1 // 忽略掉一些编译器的安全警告,_CRT_SECURE_NO_WARNINGS是一个预编译指令

#include <stdio.h> // 包含标准输入输出的头文件
#include <windows.h> // 包含Windows操作系统的头文件,其中包含了Sleep函数

// 按照题目要求,将一段长度为len的数组arr中begin到end之间的元素进行反转
void func_back(int* arr, int len, int begin, int end)
{
    // 计算需要进行多少次反转(end - len即为反转的次数)
    int sorts = end - len;

    // 外层循环表示进行sorts次反转
    for (int y = 0; y < sorts; y++)
    {
        // 内层循环表示一次反转
        for (int x = len - 1; x >= 0; x--)
        {
            // 使用异或交换两个数的值,实现交换
            *(arr + x + begin) = *(arr + x + begin) ^ *(arr + x + 1 + begin);
            *(arr + x + 1 + begin) = *(arr + x + begin) ^ *(arr + x + 1 + begin);
            *(arr + x + begin) = *(arr + x + begin) ^ *(arr + x + 1 + begin);
        }
        begin++; // 反转完之后修改起始位置
    }
}

// 打印一段长度为len的数组arr
void print(int* arr, int len)
{
    for (int x = 0; x < len; x++)
    {
        printf("%d ", *(arr + x));
    }
    printf("\n");
}

// 将一段长度为arr_len的数组arr循环左移num位
void number_back(int* arr, int arr_len, int num)
{
    for (int x = 0; x < num; x++)
    {
        int p = *arr;
        for (int x = 0; x < arr_len - 1; x++)
        {
            *(arr + x) = *(arr + x + 1);
        }
        *(arr + arr_len - 1) = p;
    }
}

int main()
{
    // 输出一些提示信息
    printf("——————————★★★★★★★★揭秘2024春晚刘谦魔术《守岁共此时》★★★★★★★★——————————\n");
	Sleep(1000);
	printf("首先,请输入你手中的四张扑克牌(为了方便这里只输入数字的牌)\n");
	printf("(注意,每一个数字之间需要使用空格或者回车符分隔开。):\n");

    // 定义并输入一个长度为8的数组arr,前4个元素存放输入的四张牌,后4个元素用于后续操作
    int arr[8] = { 0 };
    for (int x = 0; x < 4; x++)
    {
        scanf("%d", arr + x);
        *(arr + x + 4) = *(arr + x);
    }
	Sleep(1000);

    // 输出输入的四张牌
    printf("\n你手中的四张扑克牌数字是:\n");
	Sleep(1000);
    print(arr, 4);
	Sleep(1000);

    // 第一步,将数组对折并叠放在一起
    printf("\n第一步,你需要将其对折撕成两半,并叠放在一起,结果如下所示:\n");
	Sleep(1000);
    print(arr, 8);
	Sleep(1000);

    // 第二步,输入名字的长度并将牌向后移动相应的位数
    printf("\n第二步,你需要输入你名字的长度:\n");
    int name_len = 0;
    scanf("%d", &name_len);
	Sleep(1000);
    printf("\n接下来将会根据名字长度向后放几张牌,结果如下所示:\n");
	Sleep(1000);
    for (int x = 0; x < name_len; x++)
    {
        number_back(arr, 8, 1);
        print(arr, 8);
        Sleep(1000);
    }

    // 第三步,将最前面三张牌放到剩下牌的中间
    printf("\n第三步,将最前面三张牌放在剩下牌的中间,请输入目标位置\n");
	printf("(注意:目标位置在剩下的牌中第几张后面就输入几):\n");
    int the = 0;
    scanf("%d", &the);
    func_back(arr, 3, 0, the + 3);
	Sleep(1000);
    printf("\n结果如下所示:\n");
	Sleep(1000);
    print(arr, 8);
    Sleep(1000);

    // 将第一张牌放到最后
    printf("\n此时,第一张牌“%d”就是最终要拼接的牌,把它拿出来单独放好。\n\n", *arr);
    Sleep(1000);
    number_back(arr, 8, 1);
    printf("现在你手中的牌是:\n");
	Sleep(1000);
    print(arr, 7);
	Sleep(1000);

    // 第四步,根据选择的人对应数字,将最前面的牌放到剩余牌的中间
    int the_2 = 0;
    printf("\n第四步,如果你是南方人请输入1,北方人则输入2,不确定自己在南方还是北方就输入3:\n");
    scanf("%d", &the_2);
	Sleep(1000);
    printf("\n根据魔术要求和你选的哪方人对应的数字,将会拿出相应张数的最前面的牌,并放到剩余的牌中间,请输入目标位置\n");
	printf("(注意:目标位置在所有牌的第几张后面就输入几):\n");
    int the_3 = 0;
    scanf("%d", &the_3);
    func_back(arr, the_2, 0, the_3);
	Sleep(1000);
	printf("\n现在你的牌变为:\n");
	Sleep(1000);
    print(arr, 7);
	Sleep(1000);

    // 第五步,根据性别扔掉最前面的牌
    printf("\n第五步,如果你是男生请输入1,女生请输入2,将会根据所选数字扔掉最前面的牌:\n");
    int the_4;
    scanf("%d", &the_4);
    number_back(arr, 8, the_4);
	Sleep(1000);
    printf("\n丢掉之后的牌为:\n");
	Sleep(1000);
    print(arr, 7 - the_4);

    // 第六步,将最上面的牌放到最下面并重复操作7次
    printf("\n第六步,将最上面的牌放在最下面,并且重复操作7次(因为“见证奇迹的时刻”共有7个字哈哈哈!),如下所示:\n");
    for (int x = 0; x < 7; x++) 
	{
        number_back(arr, 7 - the_4, 1);
        printf("第%d次操作完成后牌为:", x + 1);
        print(arr, 7 - the_4);
        Sleep(1000);
    }
    int len = 7 - the_4;
    Sleep(1000);

    // 第七步,将最前面的牌留下或丢掉
    printf("\n最后一步,好运留下来→第一张牌放到最下面;烦恼丢出去→第一张牌丢掉。\n");
    while (len != 1)
    {
        number_back(arr, len, 1);
        printf("好运留下来→");
        print(arr, len);
        Sleep(1000);
        number_back(arr, len, 1);
        len--;
        printf("烦恼丢出去→");
        print(arr, len);
        Sleep(1000);
    }
	Sleep(1000);

    // 输出最终留下的那张牌
    printf("\n现在你的手中剩下的最后一张牌是:%d\n", *arr);
	printf("与之前单独拿出来保存的那半张牌刚好是对应的!\n\n");
	Sleep(1000);
	printf("———————★★★★★★★★恭喜你!成功复现了2024春晚刘谦魔术《守岁共此时》★★★★★★★★———————\n\n");

    return 0; // 程序结束
}

五、程序运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1449942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AndroidStdio修改安卓模拟器的安装位置

AndroidStdio修改安卓模拟器的安装位置 1.删除原有的虚拟机 可以直接删除这个avd文件&#xff0c;放心大胆删除 在这个目录下可以看到.avd文件和.ini文件。.avd占了我10G.上图是我转移.avd后截的。发现这个.ini文件&#xff0c;.ini文件就是配置文件&#xff0c;就像mysql安装…

HTML快速入门教程

HTML&#xff1a;超文本标记语言&#xff08;Hyper Text Markup Language&#xff09;&#xff0c;是通过标签的形式将内容组织起来然后共享到网络之上供其他电脑访问查看。 大家可以思考一下&#xff0c;怎么将自己电脑上的文件或图片共享给其他电脑&#xff1f; 这时候会说通…

C++ //练习 6.7 编写一个函数,当它第一次被调用时返回0,以后每次被调用返回值加1。

C Primer&#xff08;第5版&#xff09; 练习 6.7 练习 6.7 编写一个函数&#xff0c;当它第一次被调用时返回0&#xff0c;以后每次被调用返回值加1。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /**********************…

【MySQL进阶之路】千万级数据删除导致的慢查询SQL调优实战

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

Pandas数据库大揭秘:read_sql、to_sql 参数详解与实战篇【第81篇—Pandas数据库】

Pandas数据库大揭秘&#xff1a;read_sql、to_sql 参数详解与实战篇 Pandas是Python中一流的数据处理库&#xff0c;而数据库则是数据存储和管理的核心。将两者结合使用&#xff0c;可以方便地实现数据的导入、导出和分析。本文将深入探讨Pandas中用于与数据库交互的两个关键方…

2024,欢迎来到性价比时代

「不是XX买不起&#xff0c;而是YY更有性价比。」——翻开过去一年的商业消费史&#xff0c;这句话几乎可以贯穿始终。年轻消费者们追求性价比的眼光一旦定型&#xff0c;一些品牌过去被品质生活、消费升级包装出来的华丽外壳&#xff0c;很容易一击就碎。 胜出的「性价比之王…

关于nuclei-ai-extension

nuclei-ai-extension &#x1f341; Nuclei 官方开发的 利用 AI 生成 nuclei 模板的工具。Nuclei AI - 用于快速生成 Nuclei 模板的浏览器扩展&#xff0c;Nuclei AI Browser Extension建立在 cloud.projectdiscovery.io 之上&#xff0c;使用户能够从任何网页中提取漏洞信息&…

【JAVA-Day77】Java线程继承Thread类实现Runnable接口

Java线程继承Thread类实现Runnable接口 《Java线程编程指南&#xff1a;轻松掌握线程的创建和启动》摘要 &#x1f60a;引言 &#x1f680;一、什么是进程和线程 ❓二、线程如何创建 &#x1f60e;2.1 继承Thread类并重写run()方法 &#x1f4dd;2.2 实现Runnable接口并实现run…

ZISUOJ 2022年算法基础公选课练习四(Map)

说明&#xff1a; 博主为了提早预习数据结构和C的一些知识&#xff0c;自己琢磨外加查阅资料所写的代码&#xff0c;题目来源于22年初的学院老师组织的算法基础公选课的练习。我的代码甚至思路肯定存在许多不足和错误&#xff0c;欢迎大家批评指正。 题目列表&#xff1a; 问题…

操作系统-408

一、操作系统概述 1、定义 负责协调软件和硬件的计算机资源的工作为上层应用提供简易的服务操作系统是系统软件 2、功能&#xff1a; 操作系统是系统资源的管理者 处理机管理存储器管理文件管理设备管理向上层提供方便易用的服务 命令接口程序接口对硬件机器的扩展 3、特征…

(四十)大数据实战——Zabbix监控平台的部署搭建

前言 Zabbix是一款能够监控各种网络参数以及服务器健康性和完整性的软件。Zabbix使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于邮件的告警&#xff0c;这样可以快速反馈服务器的问题。基于已存储的数据&#xff0c;Zabbix提供了出色的报告和数据可视化功能。…

OpenGL-ES 学习(1)---- AlphaBlend

AlphaBlend OpenGL-ES 混合本质上是将 2 个片元的颜色进行调和(一般是求和操作)&#xff0c;产生一个新的颜色 OpenGL ES 混合发生在片元通过各项测试之后&#xff0c;准备进入帧缓冲区的片元和原有的片元按照特定比例加权计算出最终片元的颜色值&#xff0c;不再是新&#xf…

PR:剪辑工具的使用

这些是剪辑工具&#xff1a; 选择工具 用来选择、拉伸或者拖拽用&#xff0c;如果放置到片段开头和结尾处会变成红色带箭头的方框&#xff0c;可以拉升或者缩短片段的时长 如果缩短的话&#xff0c;两段视频之间会出现空挡 可以点击空挡处&#xff0c;右键点击删除波纹&#xf…

Java毕业设计-基于ssh的网上电子商城管理系统-第74期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于ssh的网上电子商城管理系统&#xff1a;前端jsp、js&#xff0c;后端 struts、spring、hibernate&#xff0c;集成商品浏览&#xff0c;商品详情&#xff0c;购物车&…

【Apache Superset】从概述、安装到运用,一篇掌握!

文章目录 什么是 Superset&#xff1f;Superset 的优势安装安装 Anaconda 包管理工具创建 Superset 的 Python 环境 下载 Superset 依赖更新工具安装 Superset配置 MySQL 元数据库初始化 Superset 数据库报错一报错二报错三数据库初始化完成 初始化 Superset报错一警告信息 启动…

【顶刊|修正】多区域综合能源系统热网建模及系统运行优化【复现+延伸】

目录 主要内容 部分代码 结果一览 下载链接 主要内容 该程序复现《多区域综合能源系统热网建模及系统运行优化》模型并进一步延伸&#xff0c;基于传热学的基本原理建立了区域热网能量传输通用模型&#xff0c;对热网热损方程线性化实现热网能量流建模&#xff…

VueCLI核心知识1:ref属性、props配置、mixin混入

1 ref 属性 ref属性类似于js原生获取DOM元素 <template><div><h1 v-text"msg" ref"title"></h1><button click"showDom">点我输出上方的Dom元素</button><School ref"sch"></School>…

消息队列RabbitMQ-使用过程中面临的问题与解决思路

消息队列在使用过程中会出现很多问题 首先就是消息的可靠性&#xff0c;也就是消息从发送到消费者接收&#xff0c;消息在这中间过程中可能会丢失 生产者到交换机的过程、交换机到队列的过程、消息队列中、消费者接收消息的过程中&#xff0c;这些过程中消息都可能会丢失。 …

UnityShader玉石效果

效果&#xff1a; 代码&#xff1a; Shader "MyShader/Jade" {Properties{_DiffuseColor("漫反射颜色",color)(1,1,1,1)_ThicknessMap("厚度图",2d)"white"{}_AddColor("叠加颜色",color)(1,1,1,1)_CubeMap("环境贴图…

【C++】const、static关键字和构造函数初始化

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 1. const修饰成员函数 1.1 语法格式 1.2 权限放大缩小 1.3 思考 1.4 解答 2. 再谈构造函数 2.1 构造函数体赋值 2.2 初始…