zoukankan      html  css  js  c++  java
  • 约瑟夫问题的变种 LA3882

    题目大意:

    N个数排成一圈,第一次删除m,以后每k个数删除一次,求最后一被删除的数。

    如果这题用链表或者数组模拟整个过程的话,时间复杂度都将高达O(nk),而n<=10000,k<=10000 目测会直接TLE。

    那么有没有其他的方法呢?答案是有的。

    我们先忽略掉m, 分析一下每k个数删除一次,那就是经典的约瑟夫问题了。

    那么,将每个数(1~n)按顺序编号为0~n-1

    设第一个删除的数的编号为x,删除x后,剩下的n-1个数可以组成一个新的约瑟夫环

    重新为新的环编号,原先为x+1的现在编号变为0,x+2变为1......

    那么在新的环中的一个编号为p的数实际上就是原先环中编号为(p+k)%n的数(画图推算)

    设f(i)为共有i个数时(0~i-1的环)最后留下的数是多少

    则 f(i)=(f(i-1)+k)%n

    相当于把i-1环的编号推算成i环的编号

    那么这一题第一次是m怎么办呢?

    也很简单,我们每次都移动K ,有n个数,那么答案就是ans[n]

    但是第一次移动的是m,所以后面的移动都有个恒定的差距(k-m)

    所以答案为:(ans[n] – (k – m) +1)% n (注意可能小于0 ,这时候要加上n)

    #include<iostream>
    #define Size 1000005
    using namespace std;
    
    int n,m,k;
    int f[Size];
    
    int main(){
        cin>>n>>k>>m;
        
        f[1]=0;
        for(int i=2;i<=n;i++){
            f[i]=(f[i-1]+k)%i;
        }
        
        int ans=(m-k+1+f[n])%n;
        if(ans<1)ans+=n;
        cout<<ans;
        
        return 0;
    } 
  • 相关阅读:
    Ueeidor 使用
    springMvc 拦截器
    redis 设置密码
    freemarker 定义公共header
    freemarker macro 使用
    freemarker ! 用法
    Android 远程连接数据库。。。。。
    Android Studio 配置
    Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
    表单,table的css
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5410212.html
Copyright © 2011-2022 走看看