题目描述
n个人排成一圈,按顺时针方向依次编号1,2,3…n。从编号为1的人开始顺时针"一二"报数,报到2的人退出圈子。这样不断循环下去,圈子里的人将不断减少。最终一定会剩下一个人。试问最后剩下的人的编号。
n很大,直接模拟题意不行,请找出规律。
输入
不超过1000组数据。
每组数据一行,每行一个正整数,代表人数n。 (1 <= n < 231)
输出
每组输入数据输出一行, 仅包含一个整数,代表最后剩下的人的编号。
样例输入
7
2
样例输出
7
1
提示
第一组数据出队顺序: 2 4 6 1 5 3
根据题意推得代码:
#include <stdio.h>
#include <stdlib.h>
#define max 1000
int main()
{
int n;
while( scanf("%d",&n) != EOF )
{
int a[max],i;
for( i = 0; i < n; i++ )
a[i] = i + 1; //创建数组,且数组长度为len
int t = 1,k = 0;
while( k != n - 1 ) //用k来重复遍历数组
{
for( i = 0; i < n ; i++ )
{
if( a[i] != 0 )
{
if( t % 2 == 0 )
{
a[i] = 0;
k++;
}
t++;
}
}
}
for( i = 0; i < n ; i++ )
{
if( a[i] != 0 ) printf("%d\n",a[i]);
}
}
return 0;
}
找到规律是很重要的,这里我还是主要是根据题目要求进行推论,还是有点暴力,但是可以用这个代码进行打表,从而发现规律
如图:
可以发现规律:所留下的编号均为奇数,且以1,1 3,1 3 5 7,1 3 5 7 9 11 13 15…出现,每次捆绑出现的个数均为2的次方。
根据等比数列的前n项和可得输入n所对应答案在哪个捆绑区域内,如:输入13,则有2^3 -1 < 13,所以13对应答案在1 3 5 7 9 11 13 15这一捆绑区域内;
又根据等差数列(以13为例,这里我选择以15为首项,-2为公差),就可已得知13对应答案为数列中第(15-13+1)=3项,即为11。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
long long fun( long long k )
{
long long b;
for( b = 0; pow( 2 , b ) < k; b++ );
return b;
}
int main()
{
long long n;
while( scanf("%lld",&n) != EOF )
{
long long m = fun( ++n ); //求得n对应结果的范围
long long c = pow( 2 , m ), g ,f;
g = c - n + 1;
f = c + 1 - 2 * g;
printf("%lld\n",f);
}
return 0;
}