E - ( ;´Д`)
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.
Example
input output 3 1
000
题意:输出字典序第k大长度为n的01串(1不能相邻),没有就输出-1
写出前几个可以发现,当最高位的1在第i位时,就相当于在第i位上填1,i-1位是0,再把最高位的1是第0(没有1)位~第i-2位的方案放在i-2~1位上,即最高位的1在第i位时f[i]=sum(f[0]~f[i-2])种方案,最后一种方案排在sum(f[0]~f[i]),到这里就可以看出怎么递归了。具体看代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
typedef long long LL;
using namespace std;
const int maxn=44;
const int mod=10056;
LL f[maxn];//最高位的1在第i位时的方案数
LL sf[maxn];//最高位的1在第i位时的最大一个方案的排名
int ans[maxn];//输出
void init()
{
f[0]=f[1]=f[2]=1;
sf[0]=1;
sf[1]=2;
sf[2]=3;
LL sum=2;
for(int i=3;i<maxn;i++)
{
f[i]=sum;
sum+=f[i-1];
sf[i-1]=sum;
}
sf[maxn-1]=sum+f[maxn-1];
}
void solve(int k)//每次递归写上第k名最高位的1
{
int x;
for(int i=0;i<maxn;i++)//找到第k名最高位的1在第几位
{
if(sf[i]>=k)
{
x=i;
break;
}
}
//printf("**%d %d %d\n",x,k,sf[x]);
if(x==0||x==1)
{
ans[43]=x;
return;
}
ans[43-x+1]=1;
solve(k%sf[x-1]);//确定最高位的1在x位,后面的数字会从第1名开始重复到最高位的1在x-2位的最后一个方案为止(包括x-2),既f[x]的第一个方案为1000...0,第二个为x000...1
}
int main()
{
int n,k;
init();
while(~scanf("%d%d",&n,&k))
{
int x;
for(int i=0;i<maxn;i++)
{
if(sf[i]>=k)
{
x=i;
break;
}
}
if(x>n){printf("-1\n");continue;}
memset(ans,0,sizeof(ans));
solve(k);
for(int i=44-n;i<44;i++)
{
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}