简略题意:字典序第k小的,满足以下条件的长度为n的01串是什么。
1.字典序小于其取反串
2.字典序小于其逆串
3.字典序小于其逆反串
给定指定长度,问有多少串满足上述条件,我们可以用数位来求得。
令
,
代表前
个
字符和后
个
字符取逆是否相同,
代表前
个
字符和后
个
字符取逆反是否相同。
那么我们考虑从前到后枚举,若当前位为
的时候的方案数
大于
,说明当前位为
,继续向后枚举, 否则说明当前位为
,
。
#define others
#ifdef poj
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#endif // poj
#ifdef others
#include <bits/stdc++.h>
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
#define eps 1e-8
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
void umax(int &a, int b) {
a = max(a, b);
}
void umin(int &a, int b) {
a = min(a, b);
}
int dcmp(double x) {
return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
freopen("data_in.txt", "r", stdin);
freopen("data_out.txt", "w", stdout);
}
namespace solver {
LL dp[55][55][2][2];
LL ans[55];
LL n, k;
LL dfs(LL l, LL r, LL v1, LL v2) {
if(l > r)return 1;
if(~dp[l][r][v1][v2]) return dp[l][r][v1][v2];
LL res = 0;
for(LL i = 0; i < 2; i++)
for(LL j = 0; j < 2; j++) {
if(ans[l] != -1 && ans[l] != i) continue;
if(ans[r] != -1 && ans[r] != j) continue;
if(v1 && i && j == 0) continue;
if(v2 && i && j) continue;
if(l == r && i != j) continue;
res += dfs(l+1, r-1, v1 && (i == j), v2 && (i != j));
}
return dp[l][r][v1][v2] = res;
}
void solve() {
cin.tie(0);
ios::sync_with_stdio(0);
cin >> n >> k;
memset(ans, -1, sizeof ans);
memset(dp, -1, sizeof dp);
ans[1] = 0;
if(dfs(1, n, 1, 1) <= k) {
puts("-1");
return ;
}
for(int i = 2; i <= n; i++) {
ans[i] = 0;
memset(dp, -1, sizeof dp);
LL val = dfs(1, n, 1, 1);
if(val <= k) {
k -= val;
ans[i] = 1;
}
}
for(int i = 1; i <= n; i++)
putchar(ans[i] + '0');
}
}
int main() {
// file();
solver::solve();
return 0;
}