codeforces 8E 数位DP

简略题意:字典序第k小的,满足以下条件的长度为n的01串是什么。
1.字典序小于其取反串
2.字典序小于其逆串
3.字典序小于其逆反串

给定指定长度,问有多少串满足上述条件,我们可以用数位来求得。
d p [ l ] [ r ] [ i n v ] [ r e v ] , i n v 代表前 l 01 字符和后 l 01 字符取逆是否相同, r e v 代表前 l 01 字符和后 l 01 字符取逆反是否相同。
那么我们考虑从前到后枚举,若当前位为 0 的时候的方案数 v 大于 k ,说明当前位为 0 ,继续向后枚举, 否则说明当前位为 1 k = v

#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;
}

猜你喜欢

转载自blog.csdn.net/meopass/article/details/80441221
今日推荐