御坂御坂题解(出自北航校赛) 约瑟夫环问题高效解决方案
御坂御坂
题目如下:
由提示可定义函数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
御坂御坂题解(出自北航校赛) 约瑟夫环问题高效解决方案相关推荐
- 北航校赛2014 预赛 题解
比赛地址 第十届北航程序设计竞赛网络预赛 A. face the truth 题意: "差点儿全部队伍都通过了题目"的含义是"有超过一半的队伍过了题目".如今n ...
- 网御星云御云成果展 促进云计算落地
本文讲的是网御星云"御云"成果展 促进云计算落地,12月4日消息,日前,网御星云在京召开了其云计算安全产品"御云"的成果展示会.会上,网御星云产品总监段伟恒分享 ...
- JavaC++题解与拓展——leetcode1823.找出游戏的获胜者【约瑟夫环】
每日一题做题记录,参考官方和三叶的题解 目录 题目要求 思路一:模拟 Java C++ 思路二:递归 Java C++ 思路三:迭代 Java C++ Rust 总结 题目要求 [这个问题似乎叫做约瑟 ...
- 北林校赛 北林oj 1332 冰尘君与扑克魔术
我并没有去北林校赛,队友回来听他们说了一道题,比较有意思. http://acm.bjfu.edu.cn/acmhome/problemdetail.do?&method=showdetail ...
- BUAAOJ989 御坂御坂 约瑟夫环
题目 BUAAOJ989 参考 代码 typedef long long ll; typedef double db; typedef pair<int, int> pll;const i ...
- 【题解】曼哈顿模拟赛(洛谷)
前言 首先%%%所有 AK/差点AK/场外AK 的神犇! 这次出题比较仓促,题目质量或许不够高.庆幸的是数据.标程没有出问题. 办比赛的目的就是共同学习.进步,大家开心就好~ std.测试数据均已打包 ...
- 杀人游戏约瑟夫环(洛谷P1145题题解,Java语言描述)
题目要求 题目链接P1145 约瑟夫环问题了解一下 约瑟夫环问题其实在数据结构里与单循环链表关系密切,但是这里模拟就完事~~ 我写过的约瑟夫环问题 AC代码(Java语言描述) import java ...
- 题解2020届天梯赛总决赛L2-4哲哲打游戏
引用 这道题其实就是简单的邻接表存储问题,但因为题目的原因只能采用尾插法,同一个点能到达的点可能非常多,如果全部遍历一遍再取数的话会超时,所以得另辟蹊径~刚好可以用二维vector(简化了next指针 ...
- 中北校赛练习里的一道题,比较难写 htu1602
00003:GCD depth 查看 提交 统计 提问 总时间限制: 5000ms 内存限制: 65536kB 描述 In mathematics, the greatest common divis ...
最新文章
- 同一账户同时只能在一处登陆(单点登陆)
- 什么心态阻碍了你职业的发展
- 元宇宙和游戏赚钱的兴趣正与日俱增
- 关于ArcGIS JS API中的map高度为400px的问题解决
- redis 公网ip访问_Redis很重要,怎么只允许指定IP访问?
- 前端学习(3219):...扩展
- java 俄文,俄文字体在word里面是什么
- 《狂人C》阅读笔记(1)
- 通力法评 | 《证券基金经营机构信息技术管理办法》解读
- linux用户个人的环境变量,linux下的变量以及系统和个人环境变量的配置文件
- VC2005运行库文件
- 深度学习模型并非“越大越好”,它可能引起气候变化问题
- 新推多多旅行搅局在线旅游市场,拼多多有多少胜算?
- SD/TF卡驱动(一)--------SD卡相关简介
- php如何去除文件扩展名,php怎样去除文件后缀名
- java el if_EL 表达式中条件运算符用于执行某种条件判断,它类似于 Java 语言中的 if-else 语句 。 ( )_学小易找答案...
- Jetpack Compose - Modifier入门篇
- 如何根据商品条码查询商品名称和价格信息?
- HD5450显卡驱动 for mac 官方免费版
- Request method ‘GET‘ not supported 405错误辨析总结
热门文章
- maven pc配置要求_竞速游戏《F1 2019》PC配置要求 GTX 1660ti即可畅玩
- 项目管理-WBS与RACI的使用
- 中国房价到底有多少泡沫?数据说话!
- Burp Suite工具详解
- ThinkPad加装SSD固态硬盘/内存条 系统迁移
- The Lost House POJ - 2057(树形dp+贪心 (双线最优子结构问题))
- uniapp 微信云开发静态网站和云函数跳转小程序
- 「备战春招/秋招系列」程序员的简历就该这样写...
- Primo Ramdisk配置教程
- 正斜杠 “/” 与反斜杠 “\”辨析