线段树解约瑟夫环,求第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 ;
}
#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 ;
}