题目:
Consider all the sequences with length (0 < N < 44), containing only the elements 0 and 1, and no two ones are adjacent (110 is not a valid sequence of length 3, 0101 is a valid sequence of length 4). Write a program which finds the sequence, which is on K-th place (0 < K < 10 9) in the lexicographically sorted in ascending order collection of the described sequences.
Input
The first line of input contains two positive integers N and K.
Output
Write the found sequence or −1 if the number K is larger then the number of valid sequences.
Sample Input
3 1
Sample Output
000
题目大意:
给出01字符串的长度,字符串要满足不能有相邻两个1,给出序号k,求出按字典序排列的第k个满足要求的字符串。
解题思路:
先求出每个长度下满足条件的字符串的个数,用动态规划,设f[i][1]和f[i][0]是长度为i且以1和0开头的满足条件的字符串的数量,如果第一位是1,则第二位一定是0,如果第一位是0,则第二位可以是0和1,所以有转换方程:f[i][1]=f[i-1][0],f[i][0]=f[i-1][1]+f[i-1][0]。初始状态f[1][1]=1,f[1][0]=0。
知道了各种长度字符串的数量如何求出第k个字符串呢?我们需要求的长度为n的字符串按字典序排列的话一定是首位为“0”的排在前面,后面是首位为“1“的字串,所以如果k小于等于首位为“0”的字符串的数量(f[n][0]),则可以知道目标字符串的首位一定是“0”,在这种情况下,我们知道当首位都是相同的“0”时,剩下的n-1位字符串按字典序仍然是首位(即长度为n的字符串的第二位)为“0”的排在前面,所以继续用这种方式判断首位是否是“0”;那如果判断的结果是k大于首位为“0”的字符串的数量怎么办呢?这时候该位的字符串是“1”,与上面的情况不同的时,这时候要将k的值减去f[n][0],这是因为进行n-1长度的字符串比较时,在首位都为“1”的情况下,这些字符串在整体所有字符串的位置已经位于所有首位为“1”的字符串后面。
代码:
#include <iostream>
using namespace std;
int main(){
int n;
long long int k;
int f[46][2];
f[1][0]=1;
f[1][1]=1;
for(int i=2;i<44;i++){
f[i][1]=f[i-1][0];
f[i][0]=f[i-1][1]+f[i-1][0];
}
while(cin>>n>>k){
if(k>f[n][1]+f[n][0]){
cout<<-1<<endl;
continue;
}
while(n){
if(f[n][0]>=k)cout<<'0';
else{
k=k-f[n][0];
cout<<'1';
}
n--;
}
cout<<endl;
}
return 0;
}