ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 17309|回复: 63

[讨论] 出个编程小题目:n个人围成圈报数踢出最后剩下几号?

[复制链接]

TA的精华主题

TA的得分主题

发表于 2016-10-18 10:45 | 显示全部楼层 |阅读模式
本帖最后由 香川群子 于 2016-10-18 10:52 编辑

题目:
有n个人围成一圈,顺序排号。
从第一个人开始报数(例如从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

扩展到报数t(t<n),报数到t的人退出圈子。

例如 n=10、t=3,那么:
1、2、3、4、5、6、7、8、9、10, 第1轮去掉3、6、9,剩下10、1、2、4、5、7、8,
第2轮去掉2、7,剩下8、10、1、4、5,
第3轮去掉1,剩下4、5、8、10,
第4轮去掉8,剩下10、4、5
第5轮去掉5,剩下10、4、(10、4),
第6轮去掉10,最后剩下4,就是答案。


TA的精华主题

TA的得分主题

发表于 2016-10-18 11:04 | 显示全部楼层
不是数到3才去掉吗,为什么10会去掉?

TA的精华主题

TA的得分主题

发表于 2016-10-18 12:02 | 显示全部楼层
老師, 我用了字典方法:

  1. Sub zz()
  2. Dim d As Object, n&, j%, Msg$
  3. Set d = CreateObject("scripting.dictionary")
  4. n = InputBox("Numbers", , 10)
  5. For i = 1 To n
  6.     d(i) = ""
  7. Next
  8. k = d.keys
  9. Do
  10.     For i = 0 To UBound(k)
  11.         If Len(k(i)) Then j = j + 1
  12.         If j = 3 Then d.Remove (k(i)): k(i) = "": j = 0
  13.     Next
  14. Loop Until d.Count = 1
  15. MsgBox "最后剩下是:" & d.keys()(0)
  16. Set d = Nothing
  17. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2016-10-18 13:49 | 显示全部楼层
  1. Sub aa()
  2. n = 10
  3. m = 3

  4. ReDim arr(1 To n)
  5. For i = 1 To n
  6.     arr(i) = i
  7. Next

  8. Do While UBound(arr) > 1
  9.     r = r + 1
  10.     Range("a1").Resize(1, UBound(arr)).Offset(r, 0) = arr
  11.     arr = bb(arr, m)
  12. Loop

  13. MsgBox arr(1)
  14. End Sub

  15. Function bb(a, b)
  16. Dim arr()
  17. arr = a
  18. n = 0
  19. k = (b - 1) \ UBound(arr) + 1
  20. For i = 1 To UBound(arr) * k
  21.     ii = (i - 1) Mod UBound(arr) + 1
  22.     m = i Mod b
  23.     If m > 0 Then
  24.         n = n Mod UBound(arr) + 1
  25.         arr(n) = arr(ii)
  26.     End If
  27. Next

  28. ReDim brr(1 To n)
  29. For i = 1 To n
  30.     If i > m Then
  31.         brr(i) = arr(i - m)
  32.     Else
  33.         brr(i) = arr(n - m + i)
  34.     End If
  35. Next
  36. bb = brr
  37. End Function
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-10-18 14:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
小花鹿 发表于 2016-10-18 11:04
不是数到3才去掉吗,为什么10会去掉?

因为是围成一圈,所以当剩余人数不足3人时,会重复去数前面的人。

第5轮去掉5,最后一剩下10、4、(10、4),
那么从10号报数=1、4号报数=2,接下来还是10号要报数=3了……于是被踢出圈子,终于只剩下4号1个人。

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-10-18 14:31 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
Chip_Kenny 发表于 2016-10-18 12:02
老師, 我用了字典方法:

你的代码可以修改一下,减少无效循环。

  1. Sub zz()
  2.     Dim d As Object, n&, j%, Msg$
  3.     Set d = CreateObject("scripting.dictionary")
  4.     n = InputBox("Numbers", , 10)
  5.     t = InputBox("Step Length", , 3)
  6.     For i = 1 To n
  7.         d(i) = ""
  8.     Next
  9.     'k = d.keys
  10.    
  11.     Do
  12.         k = d.keys '读取字典内容(更新后的剩余人数)
  13.         For i = 0 To UBound(k)
  14.             j = j + 1: If j = t Then d.Remove (k(i)): j = 0
  15.         Next
  16.     Loop Until d.Count = 1
  17.     MsgBox d.keys()(0)
  18.     Set d = Nothing
  19. End Sub
复制代码


这样显然不用在k数组中反复循环,判断是否数组对应内容为空白了。


如果投机取巧,那么第一次加入字典时就可以去掉j=t的部分。

TA的精华主题

TA的得分主题

发表于 2016-10-18 14:40 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-10-18 14:42 | 显示全部楼层
本帖最后由 香川群子 于 2016-10-18 14:52 编辑

第一次加入字典时即去掉第1轮次的代码:

  1. Sub zz()
  2.     Dim d As Object, n&, j%, Msg$
  3.     Set d = CreateObject("scripting.dictionary")
  4.     n = InputBox("Numbers", , 10)
  5.     t = InputBox("Step Length", , 3)
  6.     For i = 0 To n - 1 Step t
  7.         For j = 1 To t - 1
  8.             d(i + j) = "": If i + j = n Then Exit For
  9.         Next
  10.     Next

  11.     j = n Mod t '重新计算剩余j值
  12.     Do
  13.         k = d.keys
  14.         For i = 0 To UBound(k)
  15.             j = j + 1: If j = t Then d.Remove (k(i)): j = 0
  16.         Next
  17.     Loop Until d.Count = 1
  18.     MsgBox d.keys()(0)
  19.     Set d = Nothing
  20. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2016-10-18 15:04 | 显示全部楼层
香川群子 发表于 2016-10-18 14:42
第一次加入字典时即去掉第1轮次的代码:

香老師的精益求精指導, 衷心多謝。

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-10-18 15:11 | 显示全部楼层
Chip_Kenny 发表于 2016-10-18 12:02
老師, 我用了字典方法:

按你原来的思路,但不用字典,只用数组也可以的:

  1. Sub test1()
  2.     Dim i&, j&, k&, n&, t&
  3.    
  4.     n = 12 '圈内总人数
  5.     t = 3   '踢出圈子的步长
  6.    
  7.     ReDim a&(1 To n)
  8.     For i = 0 To n - 1 Step t
  9.         For j = 1 To t - 1
  10.             a(i + j) = i + j: If i + j = n Then Exit For
  11.         Next
  12.     Next
  13.    
  14.     j = n Mod t '第1轮尾巴剩余人数 j<t
  15.     k = n - (n - j) / t '第一轮以后剩余人数k
  16.     Do
  17.         For i = 1 To n
  18.             If a(i) Then j = j + 1: If j = t Then a(i) = 0: j = 0: k = k - 1
  19.         Next
  20.     Loop Until k = 1 '反复检查直至剩余人数k=1
  21.    
  22.     For i = 1 To n
  23.         If a(i) Then Exit For '还需要找到这最后一个人
  24.     Next
  25.     MsgBox i
  26. End Sub
复制代码


您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-25 16:36 , Processed in 0.046159 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表