zoukankan      html  css  js  c++  java
  • hiho一下 第九十四周 数论三·约瑟夫问题

     数论三·约瑟夫问题

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Hi和小Ho的班级正在进行班长的选举,他们决定通过一种特殊的方式来选择班长。

    首先N个候选人围成一个圈,依次编号为0..N-1。然后随机抽选一个数K,并0号候选人开始按从1到K的顺序依次报数,N-1号候选人报数之后,又再次从0开始。当有人报到K时,这个人被淘汰,从圈里出去。下一个人从1开始重新报数。

    也就是说每报K个数字,都会淘汰一人。这样经过N-1轮报数之后,圈内就只剩下1个人了,这个人就作为新的班长。

    举个例子,假如有5个候选人,K=3:

    初始
    0: 0 1 2 3 4
    从0号开始报数,第1次是2号报到3
    1: 0 1 - 3 4    	// 0 1 2, 2号候选人淘汰
    从3号开始报数,第2次是0号报到3
    2: - 1 3 4		// 3 4 0, 0号候选人淘汰
    从1号开始报数,第3次是4号报到3
    3: 1 3 -		// 1 3 4, 4号候选人淘汰
    从1号开始报数,第4次是1号报到3
    4: - 3			// 1 3 1, 1号候选人淘汰
      

    对于N=5,K=3的情况,最后当选班长的人是编号为3的候选人。

    小Ho:小Hi,我觉得当人数和K都确定的时候已经可以确定结果了。

    小Hi:嗯,没错。

    小Ho:我也想当班长,小Hi你能提前告诉我应该站在哪个位置么?

    小Hi:我可以告诉你怎么去求最后一个被淘汰的位置,不过具体的值你得自己去求解。

    小Ho:嗯,没问题,那么你快告诉我方法吧!

     

    输入

    第1行:1个正整数t,表示多组输入数据,1≤t≤100

    第2..t+1行:每行2个正整数n,k,第i+1行表示第i组测试数据,2≤n≤1,000,000,000。2≤k≤1,000

    输出

    第1..t行:每行1个整数,第i行表示第i组数据的解

    样例输入
    2
    5 3
    8 3
    样例输出
    3
    6
     

    解答:

    代码:
    1,开始的时候用的循环链表法,提交之后一直TLE超时,仔细排查了下,因为当k特别大的时候,n比较小的时候,需要循环很多次链表,导致超时。
     1 #include<iostream>
     2 #include<list>
     3 #include<cstdlib>
     4 using namespace std;
     5  
     6 int solve(int total,int key){
     7 
     8     list<int>* table = new list<int>();
     9 
    10     for (int i = 0; i < total; i++)
    11     {
    12         table->push_back(i);
    13     }
    14 
    15     int shout = 1;
    16     for (list<int>::iterator it = table->begin(); table->size() != 1;)
    17     {
    18         if (shout++ == key)
    19         {
    20             it = table->erase(it);
    21             shout = 1;
    22         }
    23         else
    24         {
    25             ++it;
    26         }
    27 
    28         if (it == table->end())
    29         {
    30             it = table->begin();
    31         }
    32     }
    33     return *table->begin();
    34 
    35 }
    36 int main(int argc, char* argv[])
    37 {  
    38     int n, total, key;    
    39         cin>>n;  
    40   
    41     while (n--){
    42         cin >> total >> key;
    43 
    44         cout << solve(total,key) << endl;
    45     }
    46      return 0; 
    47  }

    后来改的递推,效率提高了许多,AC了,这也体现了算法设计中,好的算法,不单单要解决实际问题,还要考虑效率问题,高效合理。

     1 #include<iostream>
     2 #include<list>
     3 #include<cstdlib>
     4 using namespace std;
     5 
     6 int solve(int total, int key)
     7 {
     8     if (total == 1)
     9         return 0;
    10     if (total < key){
    11         int anw = 0;
    12         for (int i = 2; i <= total; i++)
    13             anw = (anw + key) % i;
    14         return anw;
    15     }
    16     
    17     int anw = solve(total - total / key,key);
    18     int temp = total % key;
    19     if (anw < temp)
    20         anw = anw - temp + total;
    21     else
    22         anw = anw - temp + (anw - temp) / (key - 1);
    23     return anw;
    24 }
    25 
    26 int main(int argc, char* argv[])
    27 {
    28     int n, total, key;
    29     cin >> n;
    30 
    31     while (n--){
    32         cin >> total >> key;
    33         cout << solve(total, key) << endl;
    34     }
    35     return 0;
    36 }
     最后在补充下左老师提供的代码,很简短!!!对左老师说“我不管,反正我一定要让你会”
     1 #include "iostream"
     2 
     3 using namespace std;
     4 
     5 int n, l;
     6 
     7 int getlive(int i, int m)//i长 m数
     8 {
     9     if (i == 1)
    10         return 1;
    11     return (getlive(i - 1, m) + m - 1) % i + 1;
    12 }
    13 
    14 int main()
    15 {
    16     while (true)
    17     {
    18         cin >> n >> l;
    19         cout<<getlive(n, l);
    20     }
    21 }
  • 相关阅读:
    idea Ctrl+Alt+向下箭头 复制不起作用问题解决
    @Data 注解使用
    idea class类增加注释
    mysql 固定用户赋值数据库权限
    springboot logback 详细配置
    gitblit 增加ssh key
    uniapp内嵌H5页面和uniapp页面相互传值
    博客搬家
    反编译,java字节流 ,wirshark抓包,php转换中文
    charles 双向抓包
  • 原文地址:https://www.cnblogs.com/SeekHit/p/5457509.html
Copyright © 2011-2022 走看看