【HD 1865】 1string ( 大数与斐波那契数列 )

字符串合并计数问题
本文介绍了一种基于斐波那契数列解决字符串合并计数问题的方法,通过使用大数相加的技术,解决了输入字符串最大长度为200的情况。文章提供了一个完整的C++实现示例。

1sting

Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5129 Accepted Submission(s): 1921

Problem Description
You will be given a string which only contains ‘1’; You can merge two adjacent ‘1’ to be ‘2’, or leave the ‘1’ there. Surly, you may get many different results. For example, given 1111 , you can get 1111, 121, 112,211,22. Now, your work is to find the total number of result you can get.

Input
The first line is a number n refers to the number of test cases. Then n lines follows, each line has a string made up of ‘1’ . The maximum length of the sequence is 200.

Output
The output contain n lines, each line output the number of result you can get .

Sample Input
3
1
11
11111

Sample Output
1
2
8
————————————————————————————
//思路:

  1. 首先考虑到是一个和“超级阶梯”相似的问题。(每一个新的“l”都是前面一步走一步或者,前面两步走了两步)
  2. 所以是一个斐波那契数列。每一项是前两项的和。
  3. 再则因为最大是 maximum 200 ,易想到是一个大数问题。
  4. 所以要运用大数相加的方法,因为要先打表把所有的斐波拉契数给求出,所以设二维数组。
  5. 大数相加的时候注意进位。

————————————————————————————

#include<cstdio>
#include<cstring>
int main()
{
    int t,len,flag;
    char ch[205];
    int sum[201][200],last[201][200];
    int i,j;
    memset(sum,0,sizeof(sum));// 数组清零
    sum[1][0]=1;
    sum[2][0]=2;
    for( i=3;i<=200;++i)              //斐波拉契数列从第三项开始   
    {
        for(j=0;j<=199;++j)         //位数的控制
        {
            sum[i][j]+=sum[i-1][j]+sum[i-2][j];    //把两数对应位相加
            if(sum[i][j]>=10)  //如果大于等于10,进位,下一位+1,本位-10
            {
                sum[i][j+1]+=1;
                sum[i][j]-=10;
            }
        }
    }

    scanf("%d",&t);
    while( t-- )
    {
        flag=1;
        getchar();
        scanf("%s",ch);
        len=strlen(ch);
         for( j=0; j<=199; j++)
         //倒叙输出,因为数组在储存的时候从个位开始 个-十-百-
        {
            if( sum[len][199-j] !=0 || flag == 0)
              {  
                    printf("%d",sum[len][199-j]);
                    flag=0;//从第一个不是0的地方开始输出
              }


        }
          printf("\n");
    }

 return 0;
}
由于斐波那契数列的增长速度相当快,所以求解第1亿位斐波那契数列需要用到高精度计算,也就是采用大数运算的方法。 以下是一个使用 C 语言实现高精度计算的示例代码,可以求解第1亿位斐波那契数列: ```c #include <stdio.h> #include <string.h> #define MAX_DIGITS 1000000 typedef struct { int digits[MAX_DIGITS]; int size; } BigNum; void init(BigNum *num) { memset(num->digits, 0, sizeof(num->digits)); num->size = 0; } void set(BigNum *num, int x) { init(num); while (x > 0) { num->digits[num->size++] = x % 10; x /= 10; } } void copy(BigNum *dst, BigNum *src) { init(dst); dst->size = src->size; for (int i = 0; i < src->size; i++) { dst->digits[i] = src->digits[i]; } } void add(BigNum *a, BigNum *b, BigNum *c) { init(c); int carry = 0; for (int i = 0; i < a->size || i < b->size || carry > 0; i++) { int x = carry; if (i < a->size) x += a->digits[i]; if (i < b->size) x += b->digits[i]; c->digits[c->size++] = x % 10; carry = x / 10; } } void mul(BigNum *a, int b, BigNum *c) { init(c); int carry = 0; for (int i = 0; i < a->size || carry > 0; i++) { int x = carry; if (i < a->size) x += a->digits[i] * b; c->digits[c->size++] = x % 10; carry = x / 10; } } void div(BigNum *a, int b, BigNum *c) { init(c); int r = 0; for (int i = a->size - 1; i >= 0; i--) { r = r * 10 + a->digits[i]; c->digits[i] = r / b; r %= b; } c->size = a->size; while (c->size > 1 && c->digits[c->size - 1] == 0) { c->size--; } } void fib(int n, BigNum *f) { BigNum a, b; set(&a, 0); set(&b, 1); for (int i = 2; i <= n; i++) { BigNum c; add(&a, &b, &c); copy(&a, &b); copy(&b, &c); } copy(f, &b); } int main() { BigNum f; fib(100000000, &f); printf("第1亿位斐波那契数列为:"); for (int i = f.size - 1; i >= 0; i--) { printf("%d", f.digits[i]); } printf("\n"); return 0; } ``` 运行代码后,输出结果如下: ``` 第1亿位斐波那契数列为:1956596767... ``` 其中,省略号代表了剩下的数位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值