题目链接:戳我

貌似是高一昨天的考试题T2?????感觉挺好玩的就搞了搞qwqwq 其实是HDU上面的题啦。。。。

对于普通的约瑟夫问题,大概是n个人围成一个环,从1开始报数,数到k,那个人出队,最后留下来一个人的时候他就是胜利者,问最后胜利者是谁。

这个一般我们都用递归或者递推搞,设\(f[n]\)表示n个人的时候最后的胜利者的编号。(如果从0开始编的话),显然有\(f[1]=0\)。递推式子为\(f[i]=(f[i-1]+k)\mod i\)

但是显然O(n)的递推对于这道题来说时间复杂度还是有点高。但是之后我们发现,递推的时候,如果\(f[i-1]+k\)不超过i的话,我们可以一次多加几个,这样的话i就不需要一次加一这样转移了。

所以有(ans表示f[i])——当\(ans+k\times m<i+k-1\)的时候,我们可以一次性把这个范围内的k都加上(\(k<\frac{i-ans-1}{m-1}\))

其实还有一点小细节。。比如说加超了怎么办以及k=1的情况不能再除了,大家自己思考思考或者参考一下代码。

最后不要忘了+1。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAXN 100010
using namespace std;
long long n,k;
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
while(scanf("%lld%lld",&n,&k)!=EOF)
{
if(k==1)
{printf("%lld\n",n);continue;}
long long i=2,ans=0;
while(i<=n)
{
if(ans+2*k<i+k-1)
{
long long cur_ans=(i-ans-1)/(k-1);
if((i-ans-1)%(k-1)==0) cur_ans--;
if(i+cur_ans>n) {ans=(ans+(n-i+1)*k)%n; break;}
i+=cur_ans;
ans=(ans+cur_ans*k)%i;
}
else
ans=(ans+k)%i,i++;
}
printf("%lld\n",ans+1);
}
return 0;
}

最新文章

  1. 51nod1102(数塔)
  2. matlab播放音乐
  3. VS.Net 2015 Update3 学习(2) jquery-form, jquery-validation,jquery-validation-unobtrusive一起用
  4. Java复习笔记--java中this 关键字
  5. JSF 抽象和实现例子 (函数和属性)
  6. android 不一样的学习记录
  7. Android:控件布局(表格布局)TableLayout
  8. Ibm-jQuery教程学习笔记
  9. memcahced 更新
  10. 获取随机颜色js
  11. Adobe Photoshop CS或者CC卸载不了怎么办?
  12. Silverlight中如何自己写方法将DataTable转换为PagedCollectionView数据(动态创建类)
  13. angular1.0 app
  14. Odoo 10的Linux安装
  15. 【ASP.NET Core快速入门】(十一)应用Jwtbearer Authentication、生成jwt token
  16. mysql的使用
  17. 关于springboot整合配置pagehelper插件的方法
  18. mkpasswd命令
  19. MFC如何为程序添加标题
  20. 由表生成代码:mybatis-generator入门

热门文章

  1. Proxmox VE 设置备忘
  2. Spring IOC基础
  3. 最近学习的sql查询语句连接查询,标记一下
  4. nginx 真实ip
  5. python&#39;s unittest
  6. go_内建变量类型
  7. Unity代码里的Position和界面上的Position
  8. Spring Data JPA + layui的前台分页插件layPage实现页面的分页
  9. Hibernate事务代码规范写法
  10. 微信小程序开发教程,大多数人都搞错的八个问题