zoukankan      html  css  js  c++  java
  • 51nod1074 约瑟夫环V2 [思维题]

    V2约瑟夫环V2

    N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到 MM 的人出列,后面的人重新从1开始报数。问最后剩下的人的编号。

    例如:N = 3,M = 2。2号先出列,然后是1号,最后剩下的是3号。

    (2N1018,2M1000)(2 le N le 10^{18}, 2 le M le 1000)


    color{red}{正解部分}

    考虑先将第一个人(M1)%N(M-1)\%N处决, 然后去掉(M1)%N(M-1)\%N得到下表格第二行,
    M%NM\%N 开始重新编号, 得到下表格第三行, 设 F[i]F[i] 长度为 ii 的环最后出去的人的编号 .

    00 11 (M1)%N(M-1)\%N N1N-1
    M%NM\%N (M+1)%N(M+1)\%N (M+M1)%N(M+M-1)\%N (M+N2)%N(M+N-2)\%N
    00 11 (M1)%(N1)(M-1)\%(N-1) N2N-2

    推出递推式: F[i]=(F[i1]+M)%iF[i] = (F[i-1] + M) \% i .

    直接计算 时间复杂度为 O(N)O(N), 不能通过此题, 考虑加速转移过程,

    注意到转移只受到 模数 的影响, 可以在 模数 这里 “动手脚”,
    设当前状态为 ii, 则可以直接转移到 F[i+k]F[i+k], 其中 k=iF[i]Mk = lfloor frac{i - F[i]}{M} floor .

    这里是从 00N1N-1 标号, 因此输出答案时要加11 .


    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    const int maxn = 1e6 + 5;
    
    int M;
    
    ll N;
    
    void Work(){
            scanf("%lld%d", &N, &M);
            ll cur = 0;
            for(reg ll i = 2; i <= N; i ++){
                    if(cur + M >= i) cur += M, cur %= i;
                    else{
                            ll k = std::min(N-i+1, (i-cur)/M);
                            cur += k*M, i += k - 1;
                    }
            }
            printf("%lld
    ", cur+1);
    }
    
    int main(){
            int T; scanf("%d", &T);
            while(T --) Work();
            return 0;
    }
    
  • 相关阅读:
    Java并发之线程管理(线程基础知识)
    spring aop使用
    java动态代理
    java深拷贝与浅拷贝
    装饰模式(也叫包装模式)
    Spring基于XML方式的使用
    javaWeb域对象
    静态代理和动态代理
    getAnnotation的一个坑
    (转)文件上传org.apache.tomcat.util.http.fileupload.FileUploadException: Stream closed
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822515.html
Copyright © 2011-2022 走看看