您的位置:首页 > 其它

POJ 2886 Who Gets the Most Candies? 线段树

2012-08-13 21:58 351 查看
题意:几个人围成一个圈,第K个人开始出圈,k说出一个数(!=0)a,a>0表示左边的第a个人出列,a<0表示左边的d第a个人出列 ,直到最后一个人出圈

每个人出圈都有一个序号,如第一个出圈,第二个。。。找出所有序号中最大的反素数,反素数!!!找了一个表贴上了

这里讲的反素数 http://www.cnblogs.com/jackiesteed/articles/2018868.html

/article/6638749.html

(写的晕晕的,to me好不容易),其中找下一个位置的计算 假设位置是从 1~N,K为当前出圈的位置,该人说出的数是val ,首先N--(因为一个人出圈)

if(val>0) k=(k+val-2)%N+1,下一个相对于该人的位置是 K+val,但是该人出队以后,下一个就会前移一个位置,所以减一,然后位置1~N,还涉及到对N取余,(取余后0~N-1),所以括号里面减一,加在外面。相应的,if(val<0) k=((k+val-1)%N+N)%N+1; 跟poj 2828都属于查找吧

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define nMAX 500005
using namespace std;
struct Node
{
char name[12];
int val,num,l,r;
}node[nMAX*4];
int n,k,cnt,dest,x;
char ans[12];
int antiPrim[40]={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},
factor[40]={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};
void create(int l,int r,int u)
{
node[u].l=l,node[u].r=r;
if(l==r)
{
scanf("%s%d",&node[u].name,&node[u].val);
node[u].num=1;
return ;
}
int mid=(r+l)/2;
create(l,mid,2*u);
create(mid+1,r,2*u+1);
node[u].num=node[2*u].num+node[2*u+1].num;
}
void update(int u,int order)
{
node[u].num--;
if(node[u].l==node[u].r)
{
if(order==antiPrim[dest])
{
strcpy(ans,node[u].name);
}
else
{
n--;
if(node[u].val>0){k=(k+node[u].val-1-1)%n+1;}
else {k=((k+node[u].val-1)%n+n)%n+1;}
}
return ;
}
if(x<=node[2*u].num)update(2*u,order);
else
{
x-=node[2*u].num;
update(2*u+1,order);
}
}
int main()
{
int i;
while(~scanf("%d%d",&n,&k))
{
create(1,n,1);
for(i=0;i<35;i++)
{
if(n>=antiPrim[i]&&n<antiPrim[i+1])
dest=i;
}
int PP=n;
for(i=1;i<=antiPrim[dest];i++)//进行antiPrim[dest]次就可以了
{
x=k;
update(1,i);
}
printf("%s %d\n",ans,factor[dest]);
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: