题意: 给个你一个n,为你要构造的字符串长度, 字符串相邻的两位不能同时为1。求出n位的按字典序排列第k个字符串。
think: 首先写个dp理所应当, 有的大佬构造的是一维的(其实就是fib数列), 我第一反应就是以0结尾和以1结尾的dp...
然后那么问题就来了,在构造字符串的时候我是怎么也想不通的。。。这两天就一直在想,今天起床思路一闪, 这个dp代表的完全可以是以1开头或以0开头的方案书【从左到右】,而且转移方程也完全不用改变。
dp[i][0] = dp[i-1][0] + dp[i-1][1];
dp[i][1] = dp[i-1][0]; i<=44
代码:
#include <bits/stdc++.h> #define ll long long #define ms(x) memset(x, 0, sizeof(x)) #define inf 0x3f3f3f3f #define mf(x) memset(x, inf, sizeof(x)) using namespace std; const int N = 55; ll dp[N][3]; void init(){ ms(dp); dp[1][0] = 1; dp[1][1] = 1; for(int i=2;i<=44;i++){ dp[i][0] = dp[i-1][1] + dp[i-1][0]; dp[i][1] = dp[i-1][0]; } } int main() { init(); int n; ll tp; scanf("%d%lld", &n, &tp); if(tp > dp[n][1] + dp[n][0]){ puts("-1"); return 0; } for(int i=n;i>=1;i--){ if(tp<=dp[i][0]){ printf("0"); // tp -= dp[i][0]; } else{ printf("1"); tp -= (dp[i][0]); } } return 0; }