Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 10184 | Accepted: 3156 | |
Case Time Limit: 2000MS |
Description
N children are sitting in a circle to play a game.
N个小孩子坐成一圈玩游戏
The children are numbered from 1 to N in clockwise order. Each of them has a card with a non-zero integer on it in his/her hand. The game starts from the K-th child, who tells all the others the integer on his card and jumps out of the circle. The integer on his card tells the next child to jump out. Let A denote the integer. If A is positive, the next child will be the A-th child to the left. If A is negative, the next child will be the (−A)-th child to the right.
小孩用数字1到N来标示,以顺时针的顺序。每个人有一个卡片,上面写着一个非零的数字。游戏从第k个孩子开始,那个人念出自己的卡片数字后离开圈圈。他念的数字标示下一个跳出圈圈的孩子是谁。A表示那个数字。如果A是正数,下个孩子就是左面的第A个孩子,如果A是负数,下个孩子就是右边第(-A)个孩子
The game lasts until all children have jumped out of the circle. During the game, the p-th child jumping out will get F(p) candies where F(p) is the number of positive integers that perfectly divide p. Who gets the most candies?
游戏在所有孩子都离开圈圈后结束。游戏进行中,第p个孩子离开圈圈将会得到F(p)个蜡烛,F(p)是p的约数的个数
Input
Output
Output one line for each test case containing the name of the luckiest child and the number of candies he/she gets. If ties occur, always choose the child who jumps out of the circle first.
每组测试数据输出一行,就是拿蜡烛最多的那个孩子的名字和拿走的蜡烛数量。如果拿走的数量相同,就输出那个第一个离开的人。
Sample Input
4 2 Tom 2 Jack 4 Mary -1 Sam 1
Sample Output
Sam 3
Source
设此数是N 分解质因数 N=p1^a1*p2^a2*……*pn^an 则约数的个数是(a1+1)*(a2+1)*……*(an+1)
然后就是怎么往队伍外面撵人了。。。基本上只需要考虑撵到求因数个数最大的那个人。因为之后的人撵了也不会拿到更多蜡烛了。。。
之后就是神奇的线段树。。。基本建树和更新节点的值都很简单,主要就是那个相对位置的转换,其实我到现在也没弄太明白。。。先打个**做个备注吧。。。现在知道的是:当数为正的时候,由于自己已经被撵出去了,所以得-1。数为负的时候,由于跟自己也无关,所以不用-1,至于后面那多-的一个1,还有一堆取模运算,大概是因为取模是能取到0的。。。这里是把0那种情况给剔除了,毕竟线段树是从1-n的。。。不过到底是咋剔除的嘞。。。数学不好,待我学习一下。。。
#include <stdio.h>
#include <string.h>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 555555;
int sumtree[maxn << 2];
char name[maxn][12];
int card[maxn];
int n, k, ans = 0, sumbest = 0;
int prime[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47};
void dfs(int num, int sum, int count, int pr){
int i, p;
if (num > n){
return;
}
if (sum == sumbest && num < ans){
ans = num;
}else if (sum > sumbest){
sumbest = sum;
ans = num;
}
p = prime[pr];
for (i = 1;i <= count ;i ++){
if ((num * p) > n)
break;
dfs(num * p, sum*(i + 1), i, pr + 1);
p *= prime[pr];
}
return;
}
void build(int l, int r, int rt){
int m;
sumtree[rt] = r - l + 1;
if (l == r)
return;
m = (l + r) >> 1;
build(lson);
build(rson);
return;
}
int updata(int a, int l, int r, int rt){
int ret, m;
sumtree[rt] --;
if (l == r)
return l;
m = (l + r) >> 1;
ret = 0;
if (sumtree[rt << 1] >= a){
ret = updata(a, lson);
}else{
a -= sumtree[rt << 1];
ret = updata(a, rson);
}
return ret;
}
int main(void){
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int i;
int pos = 0;
while(scanf("%d%d", &n, &k) != EOF){
sumbest = 0;ans = 0;
dfs(1, 1, 50, 0);
build(1, n, 1);
for (i = 1;i <= n;i ++){
scanf("%s %d", name[i], &card[i]);
}
pos = 0;
for (i = 0;i < ans;i ++){
if (i != 0)
if (card[pos] > 0){
printf("> 0 k = %d, card[%d] = %d, sumtree[1] = %d\n", k, pos, card[pos], sumtree[1]);
k = (((k + card[pos] - 2) % sumtree[1] + sumtree[1]) % sumtree[1]) + 1 ;
printf("##> 0 k = %d, card[%d] = %d, sumtree[1] = %d\n", k, pos, card[pos], sumtree[1]);
}
else{
//k = (k + card[pos]) % sumtree[1];
k = (((k + card[pos] - 1) % sumtree[1] + sumtree[1]) % sumtree[1]) + 1 ;
printf("< 0 k = %d \n", k);
}
pos = updata(k, 1, n, 1);
printf("pos = %d \n", pos);
}
printf("%s %d\n", name[pos], sumbest);
}
return 0;
}