题目大意:给定两个整数n , m; 一个数列,从1开始,每进行一次操作,把自己复制一次放到后面,并在中间添加一个没出现过的最小正整数, 操作n次后 第m个位置的数字是几。
解题思路:数列有规律出现,找到最小的队列中出现的次数就好,递归问题。
题目发给定了错做次数,以及出现的位置,我们可以计算出操作n次后数列的长度, A[n] = A[n-1] * 2 +1; 因此只要不是中间那个数,我们就可以把它变成 n-1次操作里的一个数, 如果是中间那个数则直接输出, 否则看是出现在前半段还是后半段,如果是后半段则转换成前半段。
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
long long A[60];
long long solve(long long n,long long m)
{
if(m == A[n-1]+1) return n;
if(m > A[n-1] +1) m -= (A[n-1]+1);
return solve(n-1, m);
}
int main()
{
long long n, m;
A[1] = 1;
for(int i=2; i<=50; i++) A[i] = 2*A[i-1]+1;
while(~scanf("%lld%lld", &n, &m))
{
cout << solve(n, m) << endl;
}
return 0;
}