zoukankan      html  css  js  c++  java
  • 【hdoj_1250】Hat's Fibonacci(大数)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1250


    思路:本题的Fibonacci数列是扩展的四阶的Fibonacci数列,用递推关系式求解即可.


    题目提示,所求的Fibonacci数最多2500位,所以不能用已有的数据类型表示,可以采用数组存储数字,模拟加法.


    由于没有给F(n)的n最大为多少,所以需要估计一下.经过反复测试,F(7000)约为2000位左右,如果设置数组长度为2500+1,则计算得到F(7500)的结果沾满了2500+1位(),所以我们只需要计算到n=7500即可.


    在写代码的时候设置一个数组a[7500][2500+1],则a[i][j]表示待求的F(i)的i的2500+1位中的第j位.

    C++代码如下:

    #include<iostream>
    #include<string.h>
    using namespace std;
    
    #define maxn 7500//最多算到
    #define len 2500 + 1 //最多2500+1位
    int a[maxn][len];
    
    int main()
    {
    	int i,j;
    	for(i=1;i<maxn;i++)//所有的a[i]的每一位初始化为0
    		memset(a[i],0,sizeof(a[i]));
    
    	a[1][len-1] = a[2][len-1] = a[3][len-1] = a[4][len-1] = 1;//F(1)F(2)F(3)F(4)都为1
    
    	for(i=5;i<maxn;i++)//从5开始
    	{
    		int c = 0;
    		for(j=len-1;j>=0;j--)//计算F(i)
    		{
    			c += + a[i-1][j] + a[i-2][j] + a[i-3][j] + a[i-4][j] ;
    			a[i][j] = c % 10;
    			c = c / 10;
    		}
    	}
    
    	int n;
    	while(cin>>n)
    	{
    		for(i=0;i<len;i++)
    			if(a[n][i])
    				break;//去掉前导0
    		for(j=i;j<len;j++)
    			cout << a[n][j];
    		cout << endl;
    	}
    	return 0;
    }
    上述代码,提交无法通过,显示MLE.


    上述代码中a[i]的每一个元素仅存储一位数,可以用a[i]的每一个元素存多位数,例如存4位,则2500位需要625个元素存储.所以数组a可以定义为a[7500][625].如下图:


    两种存储方式的每一位都是int型的,所以第二种更节省空间,也更节省时间.采用这种方式可以避免第一种存储方式所产生的TLE或者MLE.

    C++代码如下:

    #include<iostream>
    #include<string.h>
    using namespace std;
    
    #define maxn 7500
    #define len  625   //每个元素可以存 4 位,一共要存2500位,一共需要 625个数组元素.
    int a[maxn][len];
    
    int main()
    {
    	int i,j;
    
    	for(i=1;i<maxn;i++)//一些初始化工作
    		memset(a[i],0,sizeof(a[i]));
    	a[1][len-1] = a[2][len-1] = a[3][len-1] = a[4][len-1] = 1;
    
    	for(i=5;i<maxn;i++)//从5开始
    	{
    		int c = 0;
    		for(j=len-1;j>=0;j--)//计算F(i)
    		{
    			c += (a[i-1][j] + a[i-2][j] + a[i-3][j] + a[i-4][j]);
    			a[i][j] = c % 10000;//进位处理:不是10,不是1000,因为9999仍然是四位数,只有到了10000才能进位
    			c /= 10000;
    		}
    	}
    
    	int n;
    	while(scanf("%d",&n)!=EOF)
    	{
    		if(n<=4)
    			printf("%s
    ","1");
    		else
    		{
    			int i,j;
    			for(i=0;i<len;i++)
    				if(a[n][i])
    					break;
    
    			printf("%d",a[n][i]);//先输出第一个[四位数],这样输入默认去掉前导0.
    			for(j=i+1;j<len;j++)//以后输入的中间0要保留.
    				printf("%04d",a[n][j]);//注意此处输出格式  "%04d".
    			printf("
    ");
    		}
    	}
    
    	return 0;
    }
    上述代码,提交可以通过.


    小结:


    1.由于每个元素存储4位,所以在输出的时候,除了首位的前面的0要去掉以外,后面的位的0必须保留.

    例如:输出[0023][0208][1205][0001].

    错误:printf("%d",a[n][j]);输出结果:2320812051

    正确:先输出[0023],前面的00去掉,即:printf("%d",a[n[0]]);再输出后面,有前导0的要保留即:printf("%04d",a[n][j]);(j>=1)输出结果:23020812050001


    2.采用【一个数组元素存储4位】相当于采用了10000进制,也可以采用【一个数组元素存储8位】的方法,相当于是100000000进制,那么在输出的时候也要用printf("%08d",a[n][j]);的方法.


    参考:

    http://blog.csdn.net/vsooda/article/details/7985496

    http://blog.csdn.net/zwj1452267376/article/details/47132583

  • 相关阅读:
    【转】EDK简单使用流程(3)
    【转】应用 printf 语句格式化输出字符
    【转】[FPGA博客大赛](updated)在xilinx的FPGA系统中scanf函数的使用
    BZOJ 1083 [SCOI2005]繁忙的都市
    BZOJ 2821 分块统计
    BZOJ 1034 [ZJOI2008]泡泡堂BNB
    BZOJ 1029 [JSOI2007]建筑抢修
    BZOJ 1096 [ZJOI2007]仓库建设
    BZOJ 1070 [SCOI2007]修车
    BZOJ 1040 [ZJOI2008]骑士
  • 原文地址:https://www.cnblogs.com/tensory/p/6590750.html
Copyright © 2011-2022 走看看