URAL 1081. Binary Lexicographic Sequence(简单dp)

18 篇文章 0 订阅
题意:对于原有到二进制序列,规定连续两位为1的形式不合法,剩下的按字典序排列,如000合法但011不合法101合法。输入位数N和第几个数K输出其二进制形式,若无则输出-1
方法: DP关键在于找到状态转移方程,而找方程关键在于找状态。我们从限制条件开始构造状态。以位数N和K构造是不现实的,数据量太多,我们可以位数为N的二进制数的个数作为状态,这样如果第i位填0则f[i] = f[i-1] 如果第i位填1则第i-1位只能填0,此时f[i] = f[i-2]总之,f[i] = f[i-1] + f[i-2];这个就是传说中的转移方程。

然后考虑第K个的问题,因为开头为0的数必然排在开头为1的数的前面。也就是位数为N的数共有f[i]个,其中前面的是以0开头的f[i-1]个,后面是以1开头的f[i-2]个,所以如果K小于等于f[i-1]则其第i位必然为0,然后去考虑第i-1位,此时K不变;否则其第i位必然为1第i-1位必然为0,然后去考虑第i-2位,此时K= K-f[i-1]。

以上是别人写的说的很好,就没再写一遍啊。

PS;那个规律我是写出来的、、

1081. Binary Lexicographic Sequence

Time limit: 0.5 second
Memory limit: 64 MB
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 output
3 1
000
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
///#define LL __int64
#define LL long long
#define INF 0x3f3f3ff
#define PI 3.1415926535898
#define MOD 1000000009

const int maxn = 40000005;

using namespace std;

LL num[maxn];

void Printf(int kk, int len)
{
    if(len >= 0)
    {
        if(kk > 0)
        {
            if(kk <= num[len])
            {
                cout<<0;
                Printf(kk, len-1);
            }
            else
            {
                if(len > 0)
                    cout<<10;
                else
                    cout<<1;
                Printf(kk-num[len], len-2);
            }
        }
    }
}

int main()
{
    num[0] = 1;
    num[1] = 2;
    num[2] = 3;
    for(int i = 3; i < 44; i++)
        num[i] = num[i-1]+num[i-2];
    LL n, k;
    while(cin >>n>>k)
    {
        if(k > num[n] || k < 1)
        {
            cout<<"-1"<<endl;
            continue;
        }
        Printf(k, n-1);
        cout<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值