zoukankan      html  css  js  c++  java
  • 约瑟夫环

    最近又看到了当时困惑自己很久的约瑟夫,本质上来说有点类似于dp,推导出f(n)与f(n-1)的转移关系递推求解。

    下面是最经典的约瑟夫问题,什么?链表模拟?  不存在的>_<

    https://vjudge.net/problem/51Nod-1073

    首先,将n个人编号为: 0,1,2,3........k-1,k,k+1........n-1,

    第一轮结束之后第k个人,也就是k-1将出列,剩下的人: 0,1,2,3.........k-2, k, k+1.......n-1

    下一轮从k开始我们进行重新编号,将上面的编号为:   n-k,n-k+1,n-k+2,n-k+3.............., 0,.1,.........n-k-1,

    我们如果知道了这一轮存活下来的人对应的编号是y,那么他本来的编号就是 x=(y+k)%n

    由此引出递推式 f(n)=(f(n-1)+k)%n | f(1)=0

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define inf 0x3f3f3f3f
     4 int main()
     5 {
     6     int n,k,i,j;
     7     while(cin>>n>>k){
     8         int x=0;
     9         for(i=2;i<=n;++i)
    10             x=(x+k)%i;
    11         cout<<x+1<<endl;
    12     }
    13     return 0;
    14 }

    有关这个问题的变形问题也是众多,下面我挑了一些来练习,

    https://vjudge.net/problem/UVA-1394

    题意,给出n,k,m表示,第一次先出队第m个人,然后从后面的人开始数到k的出列接着从1开始数,

    和原来的有了一点变化就是不是从第一个人开始数了,而是先出队第m然后从m+1开始,不过只有第一轮的和后面的公式不一样我们只要算出f(n-1)再推f(n)就好了。

    我们将第m人出列后从新对余下的(n-1)人编号,f(n-1)=(f(n-2)+k)%(n-1);  设x=f(n-1),则最后的答案  ans=(x+m)%n+1;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define inf 0x3f3f3f3f
     4 int main()
     5 {
     6     int n,k,i,j,m;
     7     while(cin>>n>>k>>m&&(n+k+m)){
     8         int x=0;
     9         for(i=2;i<n;++i)
    10             x=(x+k)%i;
    11         x=(m+x)%n;
    12         if(x<0) x+=n;
    13         cout<<x+1<<endl;
    14     }
    15     return 0;
    16 }

    http://acm.hdu.edu.cn/showproblem.php?pid=2211

    这个就是每次出队是k倍数的人,找到队尾之后将再次从队首开始数1,与约瑟夫有些不同,但不变的是公式推倒的过程。

    想要知道f(n),我们不妨先假设得到了x=f(n-1),这里的n表示是第几轮从头开始,我们如果将这个x转为原本的编号呢,如果我们知道他前面死了几个人的话,

    直接让x加上这个人数就好了,因为数到k就死一个,也就是说x前面有几个(k-1)就表示上一轮x前面淘汰的人,加上就好,最后边界f(k,k)=k

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define inf 0x3f3f3f3f
     4 int dfs(int n,int k)
     5 {
     6     if(n==k) return k;
     7     int x=dfs(n-n/k,k);
     8     return x+(x-1)/(k-1);
     9 }
    10 int main()
    11 {
    12     int n,k,i,j,m;
    13     cin>>m;
    14     while(m--){
    15         cin>>n>>k;
    16         cout<<dfs(n,k)<<endl;
    17     }
    18     return 0;
    19 }
  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/zzqc/p/7327996.html
Copyright © 2011-2022 走看看