御坂御坂

题目如下:

由提示可定义函数f(x):

f(1)=0

当x>1时有

f(x)=(f(x-1)+3)mod x

这个函数的意思是,f(x)是x个人的时候最后一个剩下的妹妹的编号

f(x+1)的时候是第0个人先出局了,这样子就只剩下了x个妹妹,然后第3个人就变成了f(x)的第一个出局的人,剩余人数也是x个人,那么把御坂妹妹的编号转换一下就是f(x+1)的游戏结果。

所以得出公式f(x)=(f(x-1)+3)mod x

关于这个公式我们打个表不难发现,这个公式是分段线性递增的,又因为mod每次+1而f(x)是每次+3,所以每隔x/2次增长后,f(x)会被mod减小一次,所以每经过x*3/2后,f(x)会被清零一次

就是说分段的时候x每次会增加x/2,也就是x=(3/2)*x

也就是说x是指数级递增的。

所以你可以求f是哪一段的,又因为是线性函数,所以可以直接求值。我们就能在log(n)的复杂度得到f(x)的值

然后这题的答案就是暴力跑m次f(x)来求答案,但是在log(m)次之内中一定会变成f(x)+1=f(f(x)+1)的情况,就可以直接跳出得到答案了

这题的做法

1、 O(log(n)*log(m))

log(n)的复杂度求f(n),log(m)次递归求解。

log(n)求f(n)的做法(1)

 1 #include<math.h>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<stdlib.h>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 /*f[1]=0;
 9 f[n]=(f[n-1]+3)%n
10 c[n]=c[f[n]+1]*/
11 ll f(ll n)
12 {
13     ll ans=0,m=1;
14     while(m<n)
15     {
16         ll res=m-ans;
17         ll add=res/2+(res%2);
18         if(m+add>n)break;
19         m+=add;
20         ans=ans+add*3-m;
21     }
22     return (ans+(n-m)*3)%n;
23 }
24 ll c(ll n,ll m,ll pre)
25 {
26     if(pre==n)return pre;
27     if(m==0)return n;
28     return c(f(n)+1,m-1,n);
29 }
30 int main()
31 {
32     ll t;
33     scanf("%lld",&t);
34     while(t--)
35     {
36         ll n,m;
37         scanf("%lld%lld",&n,&m);
38         printf("%lld\n",c(n,m,n+1));
39     }
40     return 0;
41 }

View Code

log(n)求f(n)的做法(2)::这个方法的原理请参考:https://www.cnblogs.com/weidiao/p/5966204.html(这个效率比上面的低一些,因为是递归所以比较慢,(1)和(2)只不过一个是正着推一个是反着推)

 1 #include<math.h>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<stdlib.h>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 /*f[1]=0;
 9 f[n]=(f[n-1]+3)%n
10 c[n]=c[f[n]+1]*/
11 ll f(ll n)
12 {
13     if(n==1)return 0;
14     if(n==2)return 1;
15     ll temp=f(n-n/3);
16     return (temp+((temp-n%3)<0?0:(temp-n%3))/2+n-n%3)%n;
17 }
18 ll c(ll n,ll m,ll pre)
19 {
20     if(pre==n)return pre;
21     if(m==0)return n;
22     return c(f(n)+1,m-1,n);
23 }
24 int main()
25 {
26     ll t;
27     scanf("%lld",&t);
28     while(t--)
29     {
30         ll n,m;
31         scanf("%lld%lld",&n,&m);
32         printf("%lld\n",c(n,m,n+1));
33     }
34     return 0;
35 }

View Code

2、O(log(log(n))*log(m)

对f(n)进行打表,预处理出来一个分段的表,然后在表上进行二分求f(n),这样子求f(n)就变成了log(log(n))的复杂度。所以时间复杂度为log(log(n))*log(m)

打表代码如下:

 1 void db()
 2 {
 3     ll x=1;
 4     ll f=0;
 5     while(x<=(ll)1e18)
 6     {
 7         printf("%lld %lld\n",x,f);
 8         ll res=x-f;
 9         ll add=(res+1)/2;
10         x+=add;
11         f=f+add*3-x;
12     }
13 }

View Code

ac代码如下:

 1 #include<math.h>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<stdlib.h>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 /*f[1]=0;
 9 f[n]=(f[n-1]+3)%n
10 c[n]=c[f[n]+1]*/
11 ll fj[]={1ll,2ll,3ll,4ll,6ll,9ll,14ll,21ll,31ll,47ll,70ll,105ll,158ll,237ll,355ll,533ll,799ll,1199ll,1798ll,2697ll,4046ll,6069ll,9103ll,13655ll,20482ll,30723ll,46085ll,69127ll,103691ll,155536ll,233304ll,349956ll,524934ll,787401ll,1181102ll,1771653ll,2657479ll,3986219ll,5979328ll,8968992ll,13453488ll,20180232ll,30270348ll,45405522ll,68108283ll,102162425ll,153243637ll,229865456ll,344798184ll,517197276ll,775795914ll,1163693871ll,1745540806ll,2618311209ll,3927466814ll,5891200221ll,8836800331ll,13255200497ll,19882800745ll,29824201118ll,44736301677ll,67104452515ll,100656678773ll,150985018159ll,226477527239ll,339716290858ll,509574436287ll,764361654431ll,1146542481646ll,1719813722469ll,2579720583704ll,3869580875556ll,5804371313334ll,8706556970001ll,13059835455001ll,19589753182502ll,29384629773753ll,44076944660629ll,66115416990944ll,99173125486416ll,148759688229624ll,223139532344436ll,334709298516654ll,502063947774981ll,753095921662471ll,1129643882493707ll,1694465823740560ll,2541698735610840ll,3812548103416260ll,5718822155124390ll,8578233232686585ll,12867349849029878ll,19301024773544817ll,28951537160317225ll,43427305740475838ll,65140958610713757ll,97711437916070635ll,146567156874105953ll,219850735311158929ll,329776102966738394ll,494664154450107591ll,741996231675161386ll};
12 ll as[]={0,1,1,0,0,0,1,1,0,1,0,0,1,1,0,1,0,1,0,0,1,1,0,1,0,0,1,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,1,1,0};
13 const int xn=102;
14 ll f(ll n)
15 {
16     int l=-1,r=xn;
17     while(l+1<r)
18     {
19         int mid=(l+r)/2;
20         if(fj[mid]>n)
21             r=mid;
22         else l=mid;
23     }
24     return as[l]+(n-fj[l])*3;
25 }
26 ll c(ll n,ll m,ll pre)
27 {
28     if(pre==n)return pre;
29     if(m==0)return n;
30     return c(f(n)+1,m-1,n);
31 }
32 void db()
33 {
34     ll x=1;
35     ll f=0;
36     while(x<=(ll)1e18)
37     {
38         printf("%lld %lld\n",x,f);
39         ll res=x-f;
40         ll add=(res+1)/2;
41         x+=add;
42         f=f+add*3-x;
43     }
44 }
45 int main()
46 {
47     ll t;
48     scanf("%lld",&t);
49     while(t--)
50     {
51         ll n,m;
52         scanf("%lld%lld",&n,&m);
53         printf("%lld\n",c(n,m,n+1));
54     }
55     return 0;
56 }

View Code

转载于:https://www.cnblogs.com/xseventh/p/8547139.html

御坂御坂题解(出自北航校赛) 约瑟夫环问题高效解决方案相关推荐

  1. 北航校赛2014 预赛 题解

    比赛地址 第十届北航程序设计竞赛网络预赛 A. face the truth 题意: "差点儿全部队伍都通过了题目"的含义是"有超过一半的队伍过了题目".如今n ...

  2. 网御星云御云成果展 促进云计算落地

    本文讲的是网御星云"御云"成果展 促进云计算落地,12月4日消息,日前,网御星云在京召开了其云计算安全产品"御云"的成果展示会.会上,网御星云产品总监段伟恒分享 ...

  3. JavaC++题解与拓展——leetcode1823.找出游戏的获胜者【约瑟夫环】

    每日一题做题记录,参考官方和三叶的题解 目录 题目要求 思路一:模拟 Java C++ 思路二:递归 Java C++ 思路三:迭代 Java C++ Rust 总结 题目要求 [这个问题似乎叫做约瑟 ...

  4. 北林校赛 北林oj 1332 冰尘君与扑克魔术

    我并没有去北林校赛,队友回来听他们说了一道题,比较有意思. http://acm.bjfu.edu.cn/acmhome/problemdetail.do?&method=showdetail ...

  5. BUAAOJ989 御坂御坂 约瑟夫环

    题目 BUAAOJ989 参考 代码 typedef long long ll; typedef double db; typedef pair<int, int> pll;const i ...

  6. 【题解】曼哈顿模拟赛(洛谷)

    前言 首先%%%所有 AK/差点AK/场外AK 的神犇! 这次出题比较仓促,题目质量或许不够高.庆幸的是数据.标程没有出问题. 办比赛的目的就是共同学习.进步,大家开心就好~ std.测试数据均已打包 ...

  7. 杀人游戏约瑟夫环(洛谷P1145题题解,Java语言描述)

    题目要求 题目链接P1145 约瑟夫环问题了解一下 约瑟夫环问题其实在数据结构里与单循环链表关系密切,但是这里模拟就完事~~ 我写过的约瑟夫环问题 AC代码(Java语言描述) import java ...

  8. 题解2020届天梯赛总决赛L2-4哲哲打游戏

    引用 这道题其实就是简单的邻接表存储问题,但因为题目的原因只能采用尾插法,同一个点能到达的点可能非常多,如果全部遍历一遍再取数的话会超时,所以得另辟蹊径~刚好可以用二维vector(简化了next指针 ...

  9. 中北校赛练习里的一道题,比较难写 htu1602

    00003:GCD depth 查看 提交 统计 提问 总时间限制: 5000ms 内存限制: 65536kB 描述 In mathematics, the greatest common divis ...

最新文章

  1. 同一账户同时只能在一处登陆(单点登陆)
  2. 什么心态阻碍了你职业的发展
  3. 元宇宙和游戏赚钱的兴趣正与日俱增
  4. 关于ArcGIS JS API中的map高度为400px的问题解决
  5. redis 公网ip访问_Redis很重要,怎么只允许指定IP访问?
  6. 前端学习(3219):...扩展
  7. java 俄文,俄文字体在word里面是什么
  8. 《狂人C》阅读笔记(1)
  9. 通力法评 | 《证券基金经营机构信息技术管理办法》解读
  10. linux用户个人的环境变量,linux下的变量以及系统和个人环境变量的配置文件
  11. VC2005运行库文件
  12. 深度学习模型并非“越大越好”,它可能引起气候变化问题
  13. 新推多多旅行搅局在线旅游市场,拼多多有多少胜算?
  14. SD/TF卡驱动(一)--------SD卡相关简介
  15. php如何去除文件扩展名,php怎样去除文件后缀名
  16. java el if_EL 表达式中条件运算符用于执行某种条件判断,它类似于 Java 语言中的 if-else 语句 。 ( )_学小易找答案...
  17. Jetpack Compose - Modifier入门篇
  18. 如何根据商品条码查询商品名称和价格信息?
  19. HD5450显卡驱动 for mac 官方免费版
  20. Request method ‘GET‘ not supported 405错误辨析总结

热门文章

  1. maven pc配置要求_竞速游戏《F1 2019》PC配置要求 GTX 1660ti即可畅玩
  2. 项目管理-WBS与RACI的使用
  3. 中国房价到底有多少泡沫?数据说话!
  4. Burp Suite工具详解
  5. ThinkPad加装SSD固态硬盘/内存条 系统迁移
  6. The Lost House POJ - 2057(树形dp+贪心 (双线最优子结构问题))
  7. uniapp 微信云开发静态网站和云函数跳转小程序
  8. 「备战春招/秋招系列」程序员的简历就该这样写...
  9. Primo Ramdisk配置教程
  10. 正斜杠 “/” 与反斜杠 “\”辨析