经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
2018-10-07 Gym-101864A丨二阶约瑟夫环丨想法
来源:cnblogs  作者:伍玖似十九  时间:2018/10/8 8:49:31  对本文有异议
题意:
多组样例,每组输入X L N,代表取1到rand(L,N)做二阶约瑟夫环(最后剩下一个人不处罚),假设每种可能性概率相等,求X位置上的人不被处罚的概率。
 
思路:
一开始很混,因为n的范围到1e15,要做得巧,首先对不被惩罚的情况,有两种:
1.成为约瑟夫环的剩下的人。
2.没有被选入环(X在某些情况大于>rand(L,N))。
然后需要一些结论:
需要知道的是,对于二阶约瑟夫环,偶数位的人必出局,那么如何计算奇数位的情况呢?对于人数为n=2^i+j的环,存活位x=2*j+1。
具体证明参考维基百科。知道这些有什么用呢?本题已知,需要存活的位置x,以及参与环的人数区间[L,N],我们需要求不被惩罚的概率,也就是找出[L,N]的参与人数中,有那些是对x有利的,找出有利情况的数量(包括不加入环和从环中幸存),就可以了。
所以可以利用n=2^i+j枚举有利条件的所有情况,最后处以gcd就是答案。
虽然代码迷之短,但是还是有很多细节需要考量的(比如逆推的n肯定要大于等于x)。
 
参考代码:
  1. #include<stdio.h>
  2. #include<algorithm>
  3. typedef long long ll;
  4. int T,Ti;
  5. ll x,l,n;
  6. int main(){
  7. scanf("%d",&T);
  8. while(Ti++<T){
  9. scanf("%lld%lld%lld",&x,&l,&n);
  10. ll sum=std::max(0ll,x-l);
  11. //when x>l,x won't be list in these rounds;
  12. if(x&1){
  13. ll j=(x-1)/2;
  14. //safe position x=2*j+1 when n=2^k+j,check every n;
  15. for(ll i=1;i+j<=n;i<<=1){
  16. if(i+j<l||i+j<x)continue;
  17. sum++;
  18. }
  19. }else if(x<=l){
  20. //x is even and can be listed in every round;
  21. printf("Case %d: 0/1\n",Ti);
  22. continue;
  23. }
  24. ll gcd=std::__gcd(sum,n-l+1);
  25. printf("Case %d: %lld/%lld\n",Ti,sum/gcd,(n-l+1)/gcd);
  26. }
  27. return 0;
  28. }
  29. /*
  30. 3
  31. 1 1 1
  32. 2 3 10
  33. 4 1 7
  34. */
View Code

 

 
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号