• 约瑟夫类问题研究


      今天考试T2挂了(众人皆A我独挂),于是写一个关于约瑟夫类问题的心得。

      约瑟夫问题:n个人(编号1~n),从1开始报数,报到m的退出,剩下的人继续从1开始报数。按顺序输出列者编号

      

      参图示。

      模拟是$O(nm)$的,然后我就死了。n,m给到1e8。

      做这么多年题大体上发现,如果你的解法超时,多半是因为处理了许多没有用的信息。

      那么看一看模拟处理出了那些没用信息:他可以知道每一轮谁死了。但是题目不需要知道这些,总之一驼人之前死掉了就可以了。

      那么我们可以这么想,要求:在不能知道每一轮是谁死了的情况下求出胜者。

      如果这个问题解决那么它应该是符合时间限制的。

      切换思路:我们考虑的时候,不把它考虑成2死了然后就没有2了,而是考虑成2死了就把2的编号重新赋给一个人。这是解题的关键。

      然后就紧紧抓住这个进行计算,首先我在最后一轮的胜者必定是0,因为只有一个人,然后我就关注这个人的编号是怎么变化的就行了。

      然后就可以推回去,每次根据标的号和人一层一层退回去。

      具体来说:剩i个人,第n+1-i个人:那么一定是从0开始找m个人,设为k,那么k=(m%i)-1号会死。

      即:0,1,2,……,k-1,k,……,n-i

      然后我们把k干掉,重新编号。

      k+1,……,n-i,0,1,2,……k-1

      0,1,……n-i-k,k,k+1,……n-i-1

      重新标号的规则就是id'=(id-k)%i

      然后我们就可以通过标号的一次次变化来递推了。

      f[i]=(f[i-1]+m)%i

    #include<cstdio>
    using namespace std;
    int f[100000020],n,m;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=2;i<=n;i++)f[i]=(f[i-1]+m)%i;
        printf("%d
    ",f[n]+1);
    }
    超长
  • 相关阅读:
    Python 资源大全中文版
    Life is short.,You need Python
    哪些 Python 库让你相见恨晚?
    中国裁判文书网全网最新爬虫分析
    关于pycharm导入其他项目时出现找不到python无法运行的问题
    禅道项目管理软件配置及使用教程
    curl
    fusionpbx 中文 汉化
    kafka operation
    golang包管理工具——glide
  • 原文地址:https://www.cnblogs.com/starsing/p/11401713.html
Copyright © 2020-2023  润新知