UVa 130 Roman Roulette

题目描述

这是一个关于约瑟夫问题变种的问题。题目背景源于历史学家弗拉维奥·约瑟夫斯的记载:在公元676767年的罗马-犹太冲突中,约瑟夫斯与404040名同伴被困在一个洞穴中。为了避免被俘,他们决定围成一个圈,按照一定规则轮流自杀。传统说法是,从某个人开始,顺时针数到第333个人就杀掉,直到只剩一人。约瑟夫斯通过计算找到了自己存活的位置。

在本题中,规则稍有不同:

  • n>0n > 0n>0个人围成一个圆圈,顺时针编号为111nnn。你的编号是111
  • 给定一个起始编号iii和一个步长kkk(k>0k > 0k>0) 。
  • iii开始,顺时针数kkk个人,杀掉这个人。
  • 然后,从被杀害者左边的人开始,再顺时针数kkk个人,选中的人负责埋葬死者,然后回到死者的位置上。
  • 接着,从刚才那个埋葬者的左边的人开始,继续顺时针数kkk个人并杀掉,重复这个过程,直到只剩一个人。

题目要求:对于给定的nnnkkk,你的程序需要找出起始编号iii1≤i≤n1 \leq i \leq n1in),使得在这个iii开始的游戏中,编号为111的人(也就是你)是最后的幸存者。

输入格式:每行包含两个整数nnnkkk。输入以一行0 0结束。n≤100n \leq 100n100

输出格式:对于每行输入,输出一个整数,即能确保你存活的安全起始位置iii

样例输入

5 2 1 5 0 0

样例输出

3 1

解题思路分析

本题是一个典型的模拟+++数学推导问题。由于n≤100n \leq 100n100,规模较小,可以直接通过模拟游戏过程来解决。核心是:对于给定的nnnkkk,我们不知道起始位置iii,但我们需要找到一个iii,使得从iii开始执行上述规则后,编号111的人最后存活。

一个直接的方法是:对于每个可能的起始位置iii(1≤i≤n1 \leq i \leq n1in),都模拟一遍游戏过程,检查编号111的人是否幸存。如果幸存,则输出这个iii。由于n≤100n \leq 100n100,最坏情况模拟100100100次,每次最多进行n−1n-1n1轮淘汰,每轮需要遍历寻找被杀者和埋葬者,总时间复杂度约为O(n3)O(n^3)O(n3),在n=100n=100n=100时完全可行。

然而,我们可以采用了另一种更高效、基于“对称性”的巧妙思路:

  1. 固定起始位置为111进行模拟:即假设游戏从编号1的人开始数(i=1i=1i=1)。我们模拟整个游戏过程,直到只剩一个人,记录下这个幸存者的编号,记为sss
  2. 利用圆的对称性推导所求的iii:当我们固定从111开始,最终幸存者是sss。现在,我们想知道:如果想让编号111的人存活,应该从哪个位置iii开始?
    • 考虑一个简单的对应关系:如果我们把整个圆圈逆时针旋转,使得原来编号为sss的人现在处于“起始位置”(即原来编号111的位置),那么在这个新的旋转后的圆圈里,从位置111开始游戏,最后的幸存者就会是原来编号为111的人(因为他现在处于原来sss的位置)。
    • 如何得到这个旋转量?从编号111的位置逆时针数到sss的位置,需要经过多少人?从111sss(顺时针编号增大),顺时针移动s−1s-1s1步到达sss。那么,从111逆时针移动到sss,相当于顺时针移动n−(s−1)=n−s+1n - (s-1) = n - s + 1n(s1)=ns+1步。
    • 更准确地说,如果我们从编号xxx开始游戏能使得编号111存活,那么当我们固定从111开始游戏时,幸存者sss的位置,就应该是从xxx开始逆时针到111的距离所对应的那个人。公式推导结果为:安全起始位置i=(n−s+1) mod n+1i = (n - s + 1) \bmod n + 1i=(ns+1)modn+1。这里取模nnn再加111是为了处理s=1s=1s=1i=1i=1i=1的情况。

因此,算法步骤为:

  1. 对于每组(n,k)(n, k)(n,k)
  2. 模拟游戏,设定起始被杀位置killed初始为(k-1) % n(因为从编号111开始,即下标000开始,数kkk个人,第一个被杀的是下标(k-1)%n)。
  3. 进行循环,直到只剩一人:
    a. 找到当前killed(被杀者)。
    b. 找到埋葬者burier:从被杀者左边开始,再数kkk个人。
    c. 将burier的位置“移动”到killed的位置(即victim[killed] = victim[burier]),然后从列表中删除burier的位置(相当于埋葬者占据了死者的位置,原埋葬者位置空出)。
    d. 更新下一次计数的起点killed为当前killed位置的下一个位置(顺时针方向)。
  4. 模拟结束后,得到幸存者编号sss
  5. 输出安全起始位置i=(n−s+1) mod n+1i = (n - s + 1) \bmod n + 1i=(ns+1)modn+1

代码实现分析

以下给出了三种能够获得通过的代码,它们核心思路一致,但在数据结构和模拟细节上略有不同。

实现一:(使用vector,原地调整)

这是最简洁的实现。使用vector<int>动态维护当前圆圈中的人。

  • killed记录当前轮次要被杀的人的下标。
  • 计算burier时,考虑从killed左边开始数kkk个人,由于burier不能是killed自己,所以计算时需要跳过killed位置。代码通过(burier + (burier >= killed)) % victim.size()来调整,确保在删除burier元素后,killed指向正确的新元素。
  • 删除burier后,更新killed为下一轮起点。

实现二:(使用固定数组,标记法)

使用固定大小数组circle,用0标记该位置的人已离开圆圈(被杀或已移动)。

  • 定义了findCW函数,从给定start下标开始,顺时针数count还在圈内的人,返回其下标。这里通过两层循环模拟环形遍历。
  • 模拟过程:先找到被杀者killed,将其标记为0。再找到埋葬者burier,将burier的值赋给killed位置(埋葬者移动到死者位置),然后将burier标记为0
  • 下一轮起点killed设为(killed + 1) % n
  • 最后遍历数组找到幸存者编号sss

实现三:(使用vector\texttt{vector}vector,标记法)

与实现二类似,但使用vector<int>而非固定数组,逻辑几乎相同,只是将数组操作改为vector\texttt{vector}vector操作。

总结

本题的关键在于理解约瑟夫问题的变种规则,并利用对称性将“寻找安全起始位置”转化为“固定起始位置模拟求幸存者,再通过公式转换”。三种实现都采用了这一核心思想,主要区别在于数据结构的选择和模拟过程中下标处理的细节。由于数据规模小,三种方法都能在时间内高效运行。


参考代码

代码一

// Roman Roulette// UVa ID: 130// Verdict: Accepted// Submission Date: 2015-12-10// UVa Run Time: 0.000s//// 版权所有(C)2015,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;intmain(intargc,char*argv[]){intn,k;while(cin>>n>>k,n||k){vector<int>victim;for(inti=1;i<=n;i++)victim.push_back(i);intkilled=(k-1)%victim.size(),burier;while(victim.size()>1){burier=(killed-1+k)%(victim.size()-1);burier=(burier+(burier>=killed))%victim.size();victim[killed]=victim[burier];victim.erase(victim.begin()+burier);killed=(killed-(burier<killed)+k)%victim.size();}cout<<(n-victim.front()+1)%n+1<<endl;}return0;}

代码二

// Roman Roulette// UVa ID: 130// Verdict: Accepted// Submission Date: 2015-12-10// UVa Run Time: 0.000s//// 版权所有(C)2015,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constintMAX_NUMBER=100;intn,k;intcircle[MAX_NUMBER+1];// 模拟计数的过程。intfindCW(intstart,intcount){for(inti=start;i<n;i++)if(circle[i]>0&&((--count)==0))returni;while(true){for(inti=0;i<n;i++)if(circle[i]>0&&((--count)==0))returni;}}// 找到幸存者的编号。intfindSurvivor(){for(inti=0;i<n;i++)if(circle[i]>0)returncircle[i];}intmain(intargc,char*argv[]){intcounter;while(cin>>n>>k,n||k){counter=n;for(inti=1;i<=n;i++)circle[i-1]=i;intkilled=0,burier;while(counter>1){killed=findCW(killed,k);circle[killed]=0;burier=findCW(killed,k);circle[killed]=circle[burier];circle[burier]=0;// 根据题意,往顺时针方向移动一个位置开始下一轮计数。killed=(killed+1)%n;counter--;}// 根据环形对称,假设幸存者的编号为s,那么从编号为1的人往逆时针// 方向数s个人,然后从此位置开始计数,则幸存者为原编号为1的人。cout<<(n-findSurvivor()+1)%n+1<<endl;}return0;}

代码三

// Roman Roulette// UVa ID: 130// Verdict: Accepted// Submission Date: 2015-12-10// UVa Run Time: 0.000s//// 版权所有(C)2015,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;vector<int>circle;// 模拟计数的过程。intfindCW(intstart,intcount){for(inti=start;i<circle.size();i++)if(circle[i]>0&&((--count)==0))returni;while(true){for(inti=0;i<circle.size();i++)if(circle[i]>0&&((--count)==0))returni;}}// 找到幸存者的编号。intfindSurvivor(){for(inti=0;i<circle.size();i++)if(circle[i]>0)returncircle[i];}intmain(intargc,char*argv[]){intn,k;while(cin>>n>>k,n||k){circle.clear();for(inti=1;i<=n;i++)circle.push_back(i);intkilled=0,burier;while(n>1){killed=findCW(killed,k);circle[killed]=0;burier=findCW(killed,k);circle[killed]=circle[burier];circle[burier]=0;// 根据题意,往顺时针方向移动一个位置开始下一轮计数。killed=(killed+1)%circle.size();n--;}// 根据环形对称,假设幸存者的编号为s,那么从编号为1的人往逆时针方向数s// 个人,然后从此位置开始计数,则幸存者为原编号为1的人。cout<<(circle.size()-findSurvivor()+1)%circle.size()+1<<endl;}return0;}

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

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

相关文章

Bilidown终极指南:从零开始掌握B站视频批量下载技巧

Bilidown终极指南&#xff1a;从零开始掌握B站视频批量下载技巧 【免费下载链接】bilidown 哔哩哔哩视频解析下载工具&#xff0c;支持 8K 视频、Hi-Res 音频、杜比视界下载、批量解析&#xff0c;可扫码登录&#xff0c;常驻托盘。 项目地址: https://gitcode.com/gh_mirror…

1小时搭建:用DEEPSEEK-OCR快速实现合同关键信息提取原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个快速原型系统&#xff0c;功能包括&#xff1a;1. 上传合同PDF/JPG文件&#xff1b;2. 自动识别合同中的关键条款&#xff08;如金额、期限、签约方&#xff09;&#xff…

企业级Android设备批量管理中的ADB问题实战

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个企业级ADB监控系统&#xff0c;专门处理DAEMON STARTED SUCCESSFULLY等状态信息。功能要求&#xff1a;1) 同时监控多台设备的ADB状态 2) 异常状态自动告警 3) 批量重启AD…

教育资料数字化:CRNN OCR处理扫描版教材

教育资料数字化&#xff1a;CRNN OCR处理扫描版教材 &#x1f4c4; OCR 文字识别在教育场景中的核心价值 随着教育信息化的不断推进&#xff0c;大量纸质教材、讲义和试卷亟需转化为可编辑、可检索的数字文本。传统的手动录入方式效率低下、成本高昂&#xff0c;且容易出错。光…

通义千问本地部署完整实战秘籍:零基础打造专属AI大脑

通义千问本地部署完整实战秘籍&#xff1a;零基础打造专属AI大脑 【免费下载链接】通义千问 FlashAI一键本地部署通义千问大模型整合包 项目地址: https://ai.gitcode.com/FlashAI/qwen 想要拥有一台永不泄密的智能助手吗&#xff1f;FlashAI通义千问本地部署方案让你在…

中文OCR技术演进:从传统方法到CRNN

中文OCR技术演进&#xff1a;从传统方法到CRNN 引言&#xff1a;OCR文字识别的技术价值与挑战 光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;是计算机视觉中最具实用价值的技术之一&#xff0c;其核心任务是从图像中自动提取可编辑的文本信息。在…

大都会艺术博物馆开放数据完整使用指南:从零开始的艺术探索之旅

大都会艺术博物馆开放数据完整使用指南&#xff1a;从零开始的艺术探索之旅 【免费下载链接】openaccess 项目地址: https://gitcode.com/gh_mirrors/ope/openaccess 大都会艺术博物馆开放访问项目为全球用户提供了一个宝贵的艺术宝库&#xff0c;包含超过47万件艺术品…

Unity卡通着色器终极指南:打造独特视觉风格的10个技巧

Unity卡通着色器终极指南&#xff1a;打造独特视觉风格的10个技巧 【免费下载链接】UnityToonShader Source code for Toon Shader tutorial for Unity. Has specular, rim lighting, and can cast and receive shadows. 项目地址: https://gitcode.com/gh_mirrors/un/UnityT…

西门子S7 - 300控制PVC配料注塑机程序开发之旅

西门子S7-300控制PVC配料注塑机程序 品牌型号 西门子300PLC和触摸屏 托利多称重仪表 称重仪表通讯&#xff0c;模拟量控制 Profibus总线桥架 配料&#xff0c;计量&#xff0c;输送&#xff0c;负压输送&#xff0c;仪表通讯系统 功能&#xff1a;计量、输送、配方、RS485称重仪…

跨学科研究:快速搭建Z-Image-Turbo与科学可视化集成环境

跨学科研究&#xff1a;快速搭建Z-Image-Turbo与科学可视化集成环境 对于科研人员来说&#xff0c;将AI图像生成技术&#xff08;如Z-Image-Turbo&#xff09;与科学数据可视化相结合&#xff0c;可以大幅提升研究成果的呈现效果。但缺乏AI专业知识往往成为门槛。本文将介绍如何…

如何快速检测SSH安全漏洞:Terrapin-Scanner完整指南

如何快速检测SSH安全漏洞&#xff1a;Terrapin-Scanner完整指南 【免费下载链接】Terrapin-Scanner This repository contains a simple vulnerability scanner for the Terrapin attack present in the paper "Terrapin Attack: Breaking SSH Channel Integrity By Seque…

【收藏必学】MCP架构OAuth安全认证实战:Python+SDK实现企业级LLM应用安全访问

如果你正在构建一个基于MCP架构的企业级LLM应用&#xff1a;各个部门都能通过客户端UI&#xff0c;经由共享的MCP Server访问内部工具与执行自动化任务。一个现实的问题是&#xff0c;你如何确保只有经过授权的员工才可以访问特定的MCP资源&#xff1f;注意这并非一个简单API-K…

FreeCAD网格修复实战:从问题诊断到完美转换的完整指南

FreeCAD网格修复实战&#xff1a;从问题诊断到完美转换的完整指南 【免费下载链接】FreeCAD This is the official source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler. 项目地址: https://gitcode.com/GitHub_Trending/fr/freecad 作…

基于卷积神经网络的OCR方案:3步完成模型部署

基于卷积神经网络的OCR方案&#xff1a;3步完成模型部署 &#x1f4d6; 项目简介 在数字化转型加速的今天&#xff0c;OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09; 技术已成为信息自动化处理的核心工具之一。无论是发票识别、文档电子…

CRNN OCR在快递物流单条码关联识别中的技巧

CRNN OCR在快递物流单条码关联识别中的技巧 &#x1f4d6; 项目简介&#xff1a;高精度通用 OCR 文字识别服务&#xff08;CRNN版&#xff09; 在快递物流行业中&#xff0c;自动化信息提取是提升分拣效率、降低人工成本的核心环节。其中&#xff0c;运单上的条码与关键字段&…

告别if-else!用Java枚举提升代码效率的5种方式

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请用Java实现两个功能相同的版本&#xff1a;1.使用传统的if-else实现状态机 2.使用枚举实现相同的状态机。要求对比展示两种实现的代码量、可读性和性能差异。包含性能测试代码&a…

AIClient-2-API:打破AI接入壁垒的技术革新之路

AIClient-2-API&#xff1a;打破AI接入壁垒的技术革新之路 【免费下载链接】AIClient-2-API Simulates Gemini CLI, Qwen Code, and Kiro client requests, compatible with the OpenAI API. It supports thousands of Gemini model requests per day and offers free use of t…

Semaphore UI自动化平台:从零开始构建企业级运维工作流

Semaphore UI自动化平台&#xff1a;从零开始构建企业级运维工作流 【免费下载链接】semaphore Modern UI for Ansible, Terraform, OpenTofu, Bash, Pulumi 项目地址: https://gitcode.com/gh_mirrors/sem/semaphore 你是否曾经为管理复杂的Ansible剧本和Terraform配置…

CRNN模型安全部署:防范OCR系统攻击

CRNN模型安全部署&#xff1a;防范OCR系统攻击 &#x1f4d6; 项目背景与安全挑战 光学字符识别&#xff08;OCR&#xff09;技术作为连接物理世界与数字信息的关键桥梁&#xff0c;已广泛应用于文档数字化、票据处理、车牌识别、智能客服等多个领域。随着深度学习的发展&…

颠覆传统:PageIndex如何用推理引擎重构文档检索体验

颠覆传统&#xff1a;PageIndex如何用推理引擎重构文档检索体验 【免费下载链接】PageIndex Document Index System for Reasoning-Based RAG 项目地址: https://gitcode.com/GitHub_Trending/pa/PageIndex 当金融分析师小王面对一份200页的财报时&#xff0c;他遇到了一…