zoukankan      html  css  js  c++  java
  • UVA1394 And Then There Was One

     题目链接

    分析:

    该题目是一个约瑟夫环的变形,区别就是第一个删除的数是m。该题的n和k都比较大,链表法O(nk),是不行的。

    因为只关心最后一个被删除的编号,而不需要完整的删除顺序,可以用递推法求解。

    先分析一下传统的约瑟夫环:n个人,编号0~n-1,每喊道k该人就被淘汰,直到最后剩下一个人。

    公式为:f(n) = (f(n-1) + k) % n,f(1)=0(这里的f(n)为最后一个人在序列剩余n个人时的编号)

    公式推导:

    初始的序号为

    (一)0, 1, ..., q-1, q, q+1, ..., n-1

    设q = k % n, 出列q-1后,序列变为

    (二)0, 1, ..., q-2, q, q+1, ..., n-1

    延长这个序列,可以得到

    (三)0, 1, ..., q-2, q, q+1, ..., n-1, n, n+1, ..., n+q-2

    从q开始取,直到n-q+2, 整个序列都减去q,得到

    (四)0, 1, ..., n-2

    经过(一)(二)(三)(四)完成了n序列到n-1序列的变化。那么这究竟是什么意思呢。仔细看下,(四)的任意元素,是不是都能找到在初始序列中的位置?

    例如(四)中的0在初始的序列编号为q。怎么找出的呢?倒着推:即(0+q)%n

    用如此的方法,即,每删除一个元素,就从它后面的一个元素开始重新编号,那么当序列中只存在一个元素时(即数完n-1次),序列的唯一元素为0.

    我们用上面的方法我们能够找出该元素在数完n-2次序列中的标号,数完n-3次数列中的标号,直到初始的序号。

    即f(i) = (f(i-1) + k) % i

    如果编号是从1~n开始的,别忘了处理下:

    f[1]=1; f[i]=(f[i-1]+m)%i  (i>1);   if(f[i]==0) f[i]=i;

    或者按着从0~n-1编号,最后加1, 即(f(n)+1)%n

    推广到第一次删除m,想象成一个编号的大圆盘,逆时针旋转m-k次,每次移动一个编号。

    本题的AC代码(参考自《训练指南》):

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    const int maxn = 10000 + 10;
    
    int f[maxn];
    
    int main(){
        int n, k, m;
        while(scanf("%d%d%d", &n, &k, &m) == 3){
            if(n == 0 && k == 0 && m == 0) break;
            f[1] = 0;
            for(int i=2; i<=n; i++) f[i] = (f[i-1]+k)%i;
            int ans = (m-k+f[n]+1) % n;
            if(ans <= 0) ans += n;
            printf("%d\n", ans);
        }
    
        return  0;
    }

    公式推导参考自:http://www.bitsucker.com/archives/7

    代码参考:《算法竞赛入门经典——训练指南》

  • 相关阅读:
    Memcached的原理分析与配置
    .Net Mvc判断用户是否登陆、未登陆跳回登陆页、三种完美解决方案
    C# ModBus Tcp客户端读取数据 完整Demo
    Log4Net配置
    commons.dbutils1.2介绍及使用
    Java通用分页
    Mysql 通用分页
    JAVA MYSQL做分页
    设置 crossdomain.xml 文件实施 HTTP 流式传输
    flash跨域策略文件crossdomain.xml配置详解
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3049077.html
Copyright © 2011-2022 走看看