用模拟每一轮有人跳出后的人数变化
因子个数可打表算出
#include <iostream>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 500005;
typedef long long ll;
#define lson rt << 1, l, m
#define rson rt << 1 | 1, m + 1, r
struct Node {
ll l, r, num;
ll mid() { return (l + r) >> 1; }
} Tree[MAXN * 4];
char name[MAXN][15];
int card[MAXN];
int table[MAXN];
void init_divide()
{
for (int i = 1; i <= MAXN; ++i)
{
++table[i];
for (int j = 2 * i; j <= MAXN; j += i)
++table[j];
}
}
void buildTree(int rt, int l, int r)
{
Tree[rt].l = l;
Tree[rt].r = r;
Tree[rt].num = r - l + 1;
if (l == r)
return;
int m = Tree[rt].mid();
buildTree(lson);
buildTree(rson);
}
int query(int rt, int n)
{
--Tree[rt].num;
if (Tree[rt].l == Tree[rt].r)
return Tree[rt].l;
if (Tree[rt << 1].num >= n)
return query(rt << 1, n);
else
return query(rt << 1 | 1, n - Tree[rt << 1].num);
}
int main(void)
{
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
/*ios::sync_with_stdio(false);
cin.tie(0);*/
init_divide();
int n, k;
while (scanf("%d %d", &n, &k) != EOF)
{
buildTree(1, 1, n);
for (int i = 1; i <= n; ++i)
scanf(" %s %d", name[i], &card[i]);
int id = 1;
for (int i = 2; i <= n; ++i)
if (table[id] < table[i])
id = i;
int mod = Tree[1].num;
int pos = 0;
card[0] = 0;
n = id;
while (n--)
{
if (card[pos] > 0)
k = ((k - 1 + card[pos] - 1) % mod + mod) % mod + 1;//因为下标是从1开始的,所以先减一,把下标调为从0开始,后再加1
else
k = ((k + card[pos] - 1) % mod + mod) % mod + 1;//card[i]<= 0则是逆时针,k不需要变为k-1
pos = query(1, k);
mod--;
}
printf("%s %d\n", name[pos], table[id]);
}
return 0;
}