这道题是一道约瑟夫环问题,只不过数据加强了,因为
不需要求出删除序列,只需要求出删除的最后一个的数字,
所以有递推的方法和线段树
#include <stdio.h>
#include <string.h>
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
const int maxn = 1000005;
int cnt[maxn << 3];
void Build ( int l, int r, int rt )
{
cnt[rt] = r-l+1;
if ( l == r )
return ;
int m = ( l+r ) >> 1;
Build ( lson );
Build ( rson );
}
void PushUP ( int rt )
{
cnt[rt] = cnt[rt << 1]+cnt[rt << 1 | 1];
}
void update ( int q, int l, int r, int rt )
{
if ( l == r )
{
cnt[rt] = 0;
return ;
}
int m = ( l+r ) >> 1;
if ( q <= cnt[rt << 1] )
update ( q, lson );
else
update ( q-cnt[rt << 1], rson );
PushUP ( rt ); //注意更新
}
int query ( int q, int l, int r, int rt )
{
if ( l == r )
return l;
int m = ( l+r ) >> 1;
if ( q <= cnt[rt << 1] )
return query ( q, lson );
else
return query ( q-cnt[rt << 1], rson );
}
int main ( )
{
int n, k, m;
while ( ~ scanf ( "%d%d%d", &n, &k, &m ) && n )
{
memset ( cnt, 0, sizeof ( cnt ) );
Build ( 1, n, 1 );
for ( int i = n-1; i >= 1; i -- ) //n-1次需要去掉的数
{
update ( m, 1, n, 1 );
m = ( m+k-2+i )%i+1; //算出当前排第几
//printf ( "%d\n", m );
}
printf ( "%d\n", query ( 1, 1, n, 1 ) ); //查询留下来的数
}
return 0;
}
。