CodeForces

暴力肯定是无法做的

当时做的时候 当成一道递推来做的 用到分治的思想

想象一串长度为2n+1的列

那么前n个为前一串数 后n个是前一串数的reverse

第n+1个数 为第几串的编号

例如 

第几串    中间的那个数    中间那个数的位置    长度

1         1         1          1

2         2           2           3

3         3         4           7 

n         n        2^(n-1)     2*len(n-1)+1

可以发现中间那个数总是代表了这一列个特征

那么把第n串的第1-2^(n-1)个数化为这个串都有效部分 因为后n个是前一串数的reverse

那么一个串的有效长度就是len[n] = 2^(n-1)

所以 给定第k个数当 k > 2^(n-1)时 可以把 它归结于前串的位置 是2*len[n] - k

当k == len[n] 的时候说明刚好 选择的就是这串的特征数(中间那个数)

否则 k < len[n] 那么就讨论 k 与 len[n-1]的情况 知道k == len[n] n就是这个数的大小

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string>
 4 #include <string.h>
 5 #include <map>
 6 #include <queue>
 7 #include <fstream>
 8 #define READ() freopen("in.txt", "r", stdin);
 9 
10 using namespace std;
11 
12 int main()
13 {
14     int n;
15     long long k;
16     string str = "1";
17     long long len[128];//有效长度
18     for (int i = 1; i <= 51; i++)
19     {
20         if (i == 1) len[i] = 1;
21         else len[i] = 2*len[i-1];
22     }
23     scanf("%d%lld", &n, &k);
24     while (k != len[n] )
25     {
26         if (k > len[n]) k = 2*len[n] - k;
27         n--;
28     }
29     cout << n << endl;
30 }
原文地址:https://www.cnblogs.com/oscar-cnblogs/p/6435446.html