pku2886 Who Gets the Most Candies?

线段树解约瑟夫环,求第i个出圈的人

反素数打的是discuss里的表

 

 

#include  < iostream >
#include 
< algorithm >
using   namespace  std;

#define  MAXN 500001

const   int  antiprime[]  =  { 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 };
const   int  factorNum[]  =  { 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 };


struct  Node{
    
int  l,r,c;
}nod[
3 * MAXN];

int  next[MAXN],n,k,kk;
char  name[MAXN][ 12 ];

void  buildtree( int  u, int  l, int  r){
    nod[u].c
= r - l + 1 ;
    nod[u].l
= l;
    nod[u].r
= r;
    
if (l == r)
        
return ;
    buildtree(
2 * u,l,(l + r) / 2 );
    buildtree(
2 * u + 1 ,(l + r) / 2 + 1 ,r);
}


void  insert( int  u, int  k){
    nod[u].c
-- ;
    
if (nod[u].l == nod[u].r){
        kk
= nod[u].l;
        
return ;
    }
    
if (nod[ 2 * u].c >= k)
        insert(
2 * u,k);
    
else
        insert(
2 * u + 1 ,k - nod[ 2 * u].c);
}

int  query( int  u, int  l, int  r){
    
if (l <= nod[u].l  &&  nod[u].r <= r)
        
return  nod[u].c;
    
int  res = 0 ;
    
if (l <= nod[ 2u ].r)
        res
+= query( 2 * u,l,r);
    
if (r >= nod[ 2 * u].l)
        res
+= query( 2 * u + 1 ,l,r);
    
return  res;
}




int  main(){
    
int  i,ith,tag, & nn = nod[ 1 ].c;
    
while (scanf( " %d%d " , & n, & k) != EOF){
        
for (i = 1 ;i <= n;i ++ )
            scanf(
" %s%d " , & name[i], & next[i]);
        buildtree(
1 , 1 ,n);

        tag
= 0 ;
        
while (antiprime[tag] <= n) // 返回antiprime中小于等于n的最大反素数下标tag
            tag ++ ;
        tag
-- ;
        ith
= antiprime[tag]; // 第ith个退出的人得到最多的糖

        
        kk
= 0 ;
        next[kk]
= 0 ;
        
while (ith -- ){
            
if (next[kk] > 0 )
                k
= ((k + next[kk] - 2 ) % nn + nn) % nn + 1 ;
            
else
                k
= ((k + next[kk] - 1 ) % nn + nn) % nn + 1 ;
            insert(
1 ,k);
        }
        printf(
" %s %d\n " ,name[kk],factorNum[tag]);
    

    }
    
return   0 ;
}

 

 

转载于:https://www.cnblogs.com/zgmf_x20a/archive/2008/11/08/1329421.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值