51nod1073 约瑟夫环

来源:互联网 发布:js获取自定义属性 编辑:程序博客网 时间:2024/06/05 12:08

1073 约瑟夫环
基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
 收藏
 关注
N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到K的人出列,后面的人重新从1开始报数。问最后剩下的人的编号。
例如:N = 3,K = 2。2号先出列,然后是1号,最后剩下的是3号。
Input
2个数N和K,表示N个人,数到K出列。(2 <= N, K <= 10^6)
Output
最后剩下的人的编号
Input示例
3 2
Output示例
3
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1073

思路:一开始用vector模拟一遍约瑟夫环,直接TLE,后来找到了一个递推公式。

先放TLE的代码:

#include <bits/stdc++.h>using namespace std;vector<int> vec;int n,k;int main(){while(~scanf("%d%d",&n,&k)){vec.clear();for(int i = 1; i <= n; i ++)vec.push_back(i);int t, tt = n;while(vec.size() > 1){if(vec.size() == tt) t = k;else{t = (k - (n - t + 1) + n) % n;}if(t == 0) t = n;vec.erase(vec.begin() + (t - 1 + n) % n);n --;}printf("%d\n",vec[0]);}return 0;}

接下来再说说递推式是怎么来的,假设存在n个人,每隔m个人就要淘汰一人,所以淘汰的第一个人为 k = (m)% n;则下一个要从k+1开始。

则现在存在的序列为:k+1,k+2.........k-1.做一个映射:

k+1    ->    0

k+2   ->     1

.

.

.

.

k-1  ->   n-1

如果我们能够推出来n-1个人时最后淘汰的是第几个人,也就能够推出n个人时最后淘汰的是那一个人。假设n-1个人时最后淘汰的是x,则我们对比下n-1时的映射关系可以发现,n-1个人第一次是从n个人的第k+1个人开始计算的,所以通过映射我们可以逆推出来n个人时最后一个淘汰的是(x + k) % n.因为 k = m % n,

所以可以得出 (x + k) % n  ==  (x + m % n ) % n  ==  (x % n + m % n) % n == (x + m ) % n;

AC代码如下:

#include <bits/stdc++.h>using namespace std;int main(){int n,m;while(~scanf("%d%d",&n,&m)){int ans = 0;for(int i = 2; i <= n; i ++)ans = (ans + m) % i;printf("%d\n",ans + 1);}return 0;}