zoukankan      html  css  js  c++  java
  • 51nod1073(约瑟夫环)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1073

    题意: 中文题诶~


    思路: 直接模拟的话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;

    代码 :
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main(void){
     5     int gg, n, k;
     6     cin >> n >> k;
     7     gg=0;
     8     for(int i=2; i<=n; i++){
     9         gg=(gg+k)%i; //前面说的f(x)只是为了我们更直观地理解,其实直接用一个变量保存上一轮序号就可以了
    10     }
    11     cout << gg+1 << endl;
    12     return 0;
    13 }
    
    
  • 相关阅读:
    oracle python操作 增删改查
    python连接oracle
    opengl问题
    [转]C++ 获取文件夹下的所有文件名
    @RequestMapping[转]
    hdu 6082
    maven/ssm框架搭建
    windows下mysql解压版安装及centos下mysql root密码忘记
    maven创建web项目
    eclipse用tomcat发布网站的目录
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6202200.html
Copyright © 2011-2022 走看看