题意: N个小孩围成一圈,他们被顺时针编号为 1 到 N。每个小孩手中有一个卡片,上面有一个非 0 的数字,游戏从第 K 个小孩开始,他告诉其他小孩他卡片上的数字并离开这个圈,他卡片上的数字 A 表明了下一个离开的小孩,如果 A 是大于 0 的,则下个离开的是左手边第 A 个,如果是小于 0 的,则是右手边的第 A 个小孩。游戏将直到所有小孩都离开,在游戏中,第 p 个离开的小孩将得到 F(p) 个糖果,F(p) 是 p 的约数的个数,问谁将得到最多的糖果。输出最幸运的小孩的名字和他可以得到的糖果。
分析:用线段树的单点更新实现某个小孩离开圈的操作,并得到下一个要离开的小孩的编号,至于如何知道谁得到的糖最多,打个反素数表就行了。
代码如下:
#include <cstdio>
#include <stack>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <list>
#include <functional>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <iomanip>
#include <cmath>
#define LL long long
#define ULL unsigned long long
#define SZ(x) (int)x.size()
#define Lowbit(x) ((x) & (-x))
#define MP(a, b) make_pair(a, b)
#define MS(arr, num) memset(arr, num, sizeof(arr))
#define PB push_back
#define F first
#define S second
#define ROP freopen("input.txt", "r", stdin);
#define MID(a, b) (a + ((b - a) >> 1))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define lrt rt << 1
#define rrt rt << 1|1
#define root 1,n,1
#define BitCount(x) __builtin_popcount(x)
#define BitCountll(x) __builtin_popcountll(x)
#define LeftPos(x) 32 - __builtin_clz(x) - 1
#define LeftPosll(x) 64 - __builtin_clzll(x) - 1
const double PI = acos(-1.0);
const LL INF = (((LL)1)<<62)+1;
using namespace std;
const double eps = 1e-5;
const int MAXN = 300 + 10;
const int MOD = 1000007;
const double M=1e-8;
const int N=500100;
typedef pair<int, int> pii;
typedef pair<int, string> pis;
const int d[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int n,k,m,st[N*4],lazy[N*4];
int p[]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,
1260,1680,2520,5040,7560,10080,15120,20160,25200,
27720,45360,50400,55440,83160,110880,166320,221760,
277200,332640,498960,554400,665280
};
int pNum[]={1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,
64,72,80,84,90,96,100,108,120,128,144,160,168,180,
192,200,216,224
};
LL ans,moresum;
int id[N];
struct node
{
char name[20];
int val;
};
node a[N];
void build(int l,int r,int rt)
{
st[rt]=r-l+1;
if (l==r) return ;
int mid=MID(l,r);
build(lson);
build(rson);
}
int updata(int k,int l,int r,int rt)
{
if (l==r) {
st[rt]--;
return r;
}
int mid=MID(l,r),t;
if (k<=st[rt<<1]) t=updata(k,lson);
else t=updata(k-st[rt<<1],rson);
st[rt]=st[lrt]+st[rrt];
return t;
}
int main()
{
int i,j,&mod=st[1];
while(~scanf("%d%d",&n,&k))
{
int pos=0;
while(p[pos]<=n) pos++;
for (i=1;i<=n;i++) {
scanf("%s %d",a[i].name,&a[i].val);
//cin>>name[i] >>id[i];
}
int v=0,u; // 从0开始编号
build(root);
a[v].val=0;
for(i=0;i<p[pos-1];i++)
{
if(a[v].val>0)
k=((k+a[v].val-2)%mod+mod)%mod+1;
else
k=((k+a[v].val-1)%mod+mod)%mod+1;
v=updata(k,1,n,1); // 让第k个人出列,并且得到他原始序列中的编号v
}
//for (i=1;i<2*r;i++) cout<<st[i]<<" "; cout<<endl;
printf("%s %d\n",a[v].name,pNum[pos-1]);
}
}