King's Game
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 263 Accepted Submission(s): 154
Problem Description
In order to remember history, King plans to play losephus problem in the parade gap.He calls n(1≤n≤5000) soldiers,
counterclockwise in a circle, in label 1,2,3...n.
The first round, the first person with label 1 counts off, and the man who report number 1 is out.
The second round, the next person of the person who is out in the last round counts off, and the man who report number 2 is out.
The third round, the next person of the person who is out in the last round counts off, and the person who report number 3 is out.
The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number n−1 is out.
And the last man is survivor. Do you know the label of the survivor?
The first round, the first person with label 1 counts off, and the man who report number 1 is out.
The second round, the next person of the person who is out in the last round counts off, and the man who report number 2 is out.
The third round, the next person of the person who is out in the last round counts off, and the person who report number 3 is out.
The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number n−1 is out.
And the last man is survivor. Do you know the label of the survivor?
Input
The first line contains a number T(0<T≤5000),
the number of the testcases.
For each test case, there are only one line, containing one integer n, representing the number of players.
For each test case, there are only one line, containing one integer n, representing the number of players.
Output
Output exactly T lines.
For each test case, print the label of the survivor.
Sample Input
2 2 3
Sample Output
2 2 Hint: For test case #1:the man who report number $1$ is the man with label $1$, so the man with label $2$ is survivor. For test case #1:the man who report number $1$ is the man with label $1$, so the man with label 1 is out. Again the the man with label 2 counts $1$, the man with label $3$ counts $2$, so the man who report number $2$ is the man with label $3$. At last the man with label $2$ is survivor.
题意:n个人排成一圈。从1开始,第i次次从前一次死掉的人往后数i个人并将它杀死,求最后的数字。
这个题目做过类似的有线段树的解法O(nlgn)但是会超时但是n比较小,于是就打个表。
看了题解的递推解法感觉自己好蠢。
打表代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define maxn 5111
#define lson tree[c].l,tree[c].mid,c<<1
#define rson tree[c].mid+1,tree[c].r,(c<<1)|1
#define pl c<<1
#define pr (c<<1)|1
int n;
struct node {
int l, r, mid, sum, num;
}tree[maxn<<4];
void build_tree (int l, int r, int c) {
tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1;
if (l == r) {
tree[c].num = 1;
tree[c].sum = 1;
return ;
}
build_tree (lson);
build_tree (rson);
tree[c].sum = tree[pl].sum + tree[pr].sum;
}
int query (int l, int r, int c, int x, int y) {
if (l == x && r == y) {
return tree[c].sum;
}
if (tree[c].mid >= y) {
return query (lson, x, y);
}
else if (tree[c].mid < x) {
return query (rson, x, y);
}
else {
return query (lson, x, tree[c].mid) + query (rson, tree[c].mid+1, y);
}
}
int update (int l, int r, int c, int id) {//从前往后将第id个数杀死 返回这个数
if (l == r) {
tree[c].num = tree[c].sum = 0;
return l;
}
int ans;
if (tree[pl].sum >= id) {
ans = update (lson, id);
}
else
ans = update (rson, id-tree[pl].sum);
tree[c].sum = tree[pl].sum + tree[pr].sum;
return ans;
}
int update2 (int l, int r, int c, int id) {//从后往前
if (l == r) {
tree[c].num = tree[c].sum = 0;
return l;
}
int ans;
if (tree[pr].sum > id)
ans = update2 (rson, id);
else
ans = update2 (lson, id-tree[pr].sum);
tree[c].sum = tree[pl].sum + tree[pr].sum;
return ans;
}
int main () {
//freopen ("in.txt", "w", stdout);
for (n = 1; n <= 5000; n++) {
build_tree (1, n, 1);
int pos = 1;
for (int i = 1; ; i++) {
if (pos > n)
pos %= n;
int id = i;
int Max = tree[1].sum;
if (Max == 1) {
printf ("%d, ", update (1, n, 1, 1));
if (n%10 == 0)
cout << endl;
break;
}
if (id > Max)
id %= Max;
if (id == 0)
id = Max;
int a1 = query (1, n, 1, pos, n);
if (a1 < id) {
id -= a1;
pos = update (1, n, 1, id);
pos++;
}
else {
pos = update2 (1, n, 1, a1-id);
pos++;
}
}
}
return 0;
}