HDU5686 Problem B【递推】

Problem B

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1323    Accepted Submission(s): 554


Problem Description
  度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列。
 

Input
这里包括多组测试数据,每组测试数据包含一个正整数 N ,代表全1序列的长度。

1N200
 

Output
对于每组测试数据,输出一个整数,代表由题目中所给定的全1序列所能形成的新序列的数量。
 

Sample Input
  
  
1 3 5
 

Sample Output
  
  
1 3 8
Hint
如果序列是:(111)。可以构造出如下三个新序列:(111), (21), (12)。
 

Source

问题链接HDU5686 Problem B

问题简述:参见上文。

问题分析

  这个问题看似一个字符串排列问题,然而只是计算排列数量,可以用斐波拉契数列来解。

  对于由所有1构成的字符串而言,用f(n)表示其长度为n时的可能数,有以下的情形:

  长度为1时,即“1”,无法合并,只有1种可能;

  长度为2时,即“11”,只有一种合并方法,字符串可以变为“11”,或“2”,有2种可能;

  长度为n时,它的长n-1的串与1连接有f(n-1)种情况,或者它的第n-1个1与第n个1合并为2,有f(n-2)种可能,合计有f(n-2)+f(n-1)种可能。

  以上可以看出,这是一个典型的斐波拉契数列。

  然而,斐波拉契数列值的增长速度太快了,需要构筑一个大整数类来解决。这里给出的程序只是简单地实现了只有+运算的无符号大整数类,解决本问题是没有问题的。

程序说明:(略)


参考链接HDU1865 1sting


AC的C++语言程序如下:

/* HDU5686 Problem B */

#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

// 无符号整数类,整数放在字符串中,可以用整数初始化。只有加运算功能。
class UBigInt {
private:
    string num;
public:
    UBigInt();
    UBigInt(int n);
    void setNumber(string s);
    const string& getNumber(); // retrieves the number
    UBigInt operator + (UBigInt b);
private:
    string add(string number1, string number2);
};

UBigInt::UBigInt() { // empty constructor initializes zero
    num = "0";
}

UBigInt::UBigInt(int n) {
    stringstream ss;
    string s;
    ss << n;
    ss >> s;
    setNumber(s);
}

void UBigInt::setNumber(string s) {
    num = s;
}

const string& UBigInt::getNumber() { // retrieves the number
    return num;
}

UBigInt UBigInt::operator + (UBigInt b) {
    UBigInt addition;
    addition.setNumber( add(getNumber(), b.getNumber() ) );

    return addition;
}

string UBigInt::add(string number1, string number2) {
    string add = (number1.length() > number2.length()) ?  number1 : number2;

    int diffLength = abs( (int) (number1.size() - number2.size()) );
    if(number1.size() > number2.size())
        number2.insert(0, diffLength, '0'); // put zeros from left
    else// if(number1.size() < number2.size())
        number1.insert(0, diffLength, '0');

    char carry = 0;
    for(int i=number1.size()-1; i>=0; --i) {
        add[i] = (carry+(number1[i]-'0')+(number2[i]-'0')) + '0';

        if(i != 0) {
            if(add[i] > '9') {
                add[i] -= 10;
                carry = 1;
            } else
                carry = 0;
        }
    }
    if(add[0] > '9') {
        add[0]-= 10;
        add.insert(0,1,'1');
    }
    return add;
}

void fib(int n)
{
    if(n == 1) {
        cout << 1 << endl;
    } else if(n == 2) {
        cout << 2 << endl;
    } else {
         UBigInt f1 = 1;
         UBigInt f2 = 2;
         UBigInt temp;
         n -= 2;
         while(n--) {
             temp = f2;
             f2 = f1 + f2;
             f1 = temp;
         }
         cout << f2.getNumber() << endl;
    }
}

int main(void)
{
    int n;

    while(scanf("%d", &n) != EOF) {
        fib(n);
    }

    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值