百度之星-资格赛Problem B

来源:互联网 发布:游戏编程需要数学吗 编辑:程序博客网 时间:2024/06/05 00:10

Problem B
Accepts: 1408 Submissions: 5317
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列。
Input
这里包括多组测试数据,每组测试数据包含一个正整数N,代表全1序列的长度。
1\leq N \leq 2001≤N≤200
Output
对于每组测试数据,输出一个整数,代表由题目中所给定的全1序列所能形成的新序列的数量。
Sample Input
1
3
5
Sample Output
1
3
8
Hint
如果序列是:(111)。可以构造出如下三个新序列:(111), (21), (12)。
分析:
和资格赛的第二题一样,直接用递推即可。再考虑第n个(最后一个)1时,(1):他不合并,剩下的n-1个可以按规定合并,所以a[n]=a[n-1];(2):他与第n-1个1合并,剩下的n-2个可以按规定合并。所以a[n]=a[n-1]+a[n-2];
需要注意的是:题目N<200,所以要考虑到高进度加法问题。以下有两种高精度加法(由于200还是很小的所以第一种也可以)。第二种是实现一个大整数类,可以达到第10000位,使他支持高精度加法,有点难度,建议读者慢慢研究体会。
方法一:

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 1005;int a[maxn][maxn];void init(int a[maxn][maxn]){    memset(a,0,sizeof(a));    a[1][0] = 1;    a[2][0] = 2;    for(int i = 3; i <= 1002; i++)    {        for(int j = 0; j < maxn ; j++) { a[i][j] += a[i-1][j] + a[i-2][j]; if(a[i][j] >= 10)            {                a[i][j] -= 10;                a[i][j+1]++;            }        }    }}int main(){    int n,i;    init(a);    while(scanf("%d", &amp;n) != EOF)    {        for(i = 1000; i >= 0; i--)            if(a[n][i]) break;        for(; i >= 0; i--)            printf("%d",a[n][i]);        printf("\n");    }    return 0;}

方法二:

#include <iostream>#include <string.h>#include <cstdio>using namespace std;const int MAXN = 100000000;const int N = 500;const int M = 10000;struct bign {    int len;    int s[N];    bign() {    this -> len = 1;    memset(s, 0, sizeof(s));    }    bign (int number) {*this = number;}    bign (const char* number) {*this = number;}    bign change(bign cur) {    bign now;    now = cur;    for (int i = 0; i < cur.len; i++) now.s[i] = cur.s[cur.len - i - 1]; return now; } void delZore() { // 删除前导0.     bign now = change(*this); while (now.s[now.len - 1] == 0 && now.len > 1) {        now.len--;    }    *this = change(now);    }    void put() {    // 输出数值。    delZore();    printf("%d", s[0]);    for (int i = 1; i < len; i++)        printf("%08d", s[i]);    }    bign operator = (const char *number) {    memset(s, 0, sizeof(s));    int dist = strlen(number);    int k = dist % 8;    for (int i = 0; i < k; i++)        s[0] = s[0] * 10 + number[i] - '0';    int cnt = 0;    for (int i = k; i < dist; i++, cnt++)        s[cnt / 8 + 1] = s[cnt / 8 + 1] * 10 + number[i] - '0';    len = cnt / 8 + 1;    return *this;    }    bign operator = (int number) {    char string[N];    sprintf(string, "%d", number);    *this = string;    return *this;    }    bign operator + (const bign &cur){    bign sum, a, b;    sum.len = 0;    a = a.change(*this);    b = b.change(cur);    for (int i = 0, g = 0; g || i < a.len || i < b.len; i++){        int x = g;        if (i < a.len) x += a.s[i];        if (i < b.len) x += b.s[i];        sum.s[sum.len++] = x % MAXN;        g = x / MAXN;    }    return sum.change(sum);    }};bign num[M + 10];int main() {    int n;    num[1]=1;    num[2]=2;    num[3]=3;    num[4]=5;    for (int i = 5; i < M + 5; i++)    num[i] = num[i - 1] + num[i - 2];    while (scanf("%d", &n) == 1) {    num[n].put();    printf("\n");    }    return 0;}
1 0