zoukankan      html  css  js  c++  java
  • 约瑟夫环

    1073 约瑟夫环

    约瑟夫环的公式为:f(1) = 0;

             f(n) = (f(n-1)+k)%n (n>1)

    推理过程如下:

    思路: 直接模拟的话O(n*k)的时间复杂度,按照套路来的话这样的题一般是能找规律的;
    我们先将n个人的编号改成0~n-1(别问为什么,套路而已),那么第1次报到号码为k-1的人出列,圈里还剩下n-1个人
    我们对比一下出列前后的编号:

    出列前: 0, 1, 2, 3, 4, 5, 6, ...k-2, k-1, k... n-1
    出列后: n-k+1,..................n-2, , 1... n-k

    我们可以发现留下的人编号和留下来之前是一一对应的,那么要是能找到对应关系的话问题就迎刃而解了,不过现在数据太多了不好找
    (偶就是这里找错了规律然后只过了样例),我们接着往下想想...
    按照前面的规律,第n次报数时只有一个人,我们给他重新编号为0.前面我们也知道了某一轮某个人的编号和上一轮是对应的,最后留下的人此时的编号为0,
    那么只要我们由它上溯并找到它在第一轮时的编号答案就出来了啦~
    我们用f(x)表示最后留下来那个人在第n-x+1轮中的编号(这样做我们就是由f(1)推f(n),更直观一些,反之由f(n)推f(1)也是可以的),那么f(n)+1就是
    最终答案了啦.很显然有f(1)=0(因为此时只剩下一个人了嘛),接下来我们需要找到两轮编号之间的映射关系,这个可以有枚举k和x得到,这里就不写枚举
    过程了啦~
    最后我们可以得到公式 f(x)=(f(x-1)+k)%x;


    来源为:http://www.cnblogs.com/geloutingyu/p/6202200.html
     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 
     5 int main(){
     6     int n,k;
     7     cin >> n >> k;
     8     int f = 0;
     9     for(int i = 2; i <= n; i ++){
    10         f = (f+k)%i;
    11     }
    12     cout << f+1 << endl;
    13     return 0;
    14 }
  • 相关阅读:
    async中series的实现 javascript构件
    6.算法-计数排序
    5.算法-快速排序
    4.堆排序
    3.分治法研究-搜索数组中的最长连续递增子集
    字典树(Trie)学习笔记
    并查集笔记
    求树的遍历
    P1087 FBI树
    P5017 摆渡车
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/7106565.html
Copyright © 2011-2022 走看看