POJ2413 How many Fibs(高精度)(AC)

本文介绍了一种计算大数范围内Fibonacci数的方法,包括如何生成指定范围内的Fibonacci数列,并通过特定算法找出给定区间内存在的Fibonacci数。此算法适用于处理非常大的数字输入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

How many Fibs?
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11896 Accepted: 4312

Description

Recall the definition of the Fibonacci numbers: 
f1 := 1 

f2 := 2 

fn := fn-1 + fn-2     (n>=3) 

Given two numbers a and b, calculate how many Fibonacci numbers are in the range [a,b].

Input

The input contains several test cases. Each test case consists of two non-negative integer numbers a and b. Input is terminated by a=b=0. Otherwise, a<=b<=10100. The numbers a and b are given with no superfluous leading zeros.

Output

For each test case output on a single line the number of Fibonacci numbers fi with a<=fi<=b.

Sample Input

10 100
1234567890 9876543210
0 0

Sample Output

5
4

//这道题的意思就是在a和b之间有多少个fib函数就可以到了
//10 100找到10位到100位之间的fib数

//这么大的输入输出肯定要用数组了

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string>  

#define MAXN 150
#define MAXF 1000

int first[MAXN];
int second[MAXN];

int firstweishu  = 0;
int secondweishu = 0;

int ans = 0;

int fibnum[MAXF][MAXN]; //存所有的fib数
int weishu[MAXF];  //存每个fib数占的位数

//#define max(a,b) (a) >=(b)?(a):(b)

//WA了无数次,最后还是自己的find函数写的有问题, 因为需要考虑90 120这种情况,90不是fib数,120也不是,中间也没有fib数,因此90在找比它大的fib数的时候是找不到的
//因为在比较位数比它大的数,就应该设置findflag =1,然后比较和end的数,这个改了就可以了
//另外case也考虑了0982 9999这样的情况,但是应该是不会出现的
//FIb数生成还是没问题的
//find的思路是1 2, start是1,end是2,那就是要找到在1和2之间的数,start找到>=1的序列, end<=2的序列, start如果找到比它大的数,那还要check下这个数是否比end大
//如果比end大那说明这个区间肯定没有fib数
//end要找的是比它小的数,因此从最后一个和它同长度的比较起,如果位数比它短,那可以直接返回了,因为start有比较是否比end大,因为end这边不需要再比较了
//最终AC

int max(int a,int b)
{
	if (a >= b)
	{
		return a;
	}
	else
	{
		return b;
	}	
}


int index = 3;


char a[MAXN] = { '\0' };
char  b[MAXN] = { '\0' };


void init()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < MAXN;i++)
	{
		first[i] = 0;
		second[i] = 0;
	}
	
	ans = 0;
	return;
}

void initmatrix()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < MAXN; i++)
	{
		a[i] = '\0';
		b[i] = '\0';
	}
	return;
}

void initfib()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < MAXF; i++)
	{
		weishu[i] = 0;
		for (j = 0; j < MAXN; j++)
		{
			fibnum[i][j] = 0;
		}
	}
	return;
}


int fib(int a)
{
	return fib(a-1) + fib(a-2);
}

int strlength(char* s)
{
	int size = 0;
	int findshuzi = 0;
	while ('\0' != *s)
	{
		size += 1;
		s += 1;
	}

	return size;
}


int strlengths(char* s)
{
	int size = 0;
	int findshuzi = 0;
	while ('\0' != *s)
	{
		if (('0' == *s) && (0 == findshuzi))
		{

		}
		else
		{
			size += 1;
			findshuzi = 1;
		}
		s += 1;
	}

	if (0 == size) size += 1;//防止0的情况
	return size;
}

void parse()
{
	int i = 0;
	int j = 0;
	
	firstweishu  = strlength(a);
	secondweishu = strlength(b);

	i = firstweishu - 1;
	j = 0;
	while ('\0' != a[j])
	{
		first[i] = a[j] - '0';
		i -= 1;
		j += 1;
	}

	i = secondweishu - 1;
	j = 0;
	while ('\0' != b[j])
	{
		second[i] = b[j] - '0';
		i -= 1;
		j += 1;
	}

	firstweishu = strlengths(a);
	secondweishu = strlengths(b);
	return;
}

//获取105位以内的所有fib数
void getfib()
{
	int c = 0;
	int jinwei = 0;
	int i = 0;
	int d = 0;

	index = 3;

	fibnum[1][0] = 1;
	fibnum[2][0] = 2;
	weishu[1] = 1;
	weishu[2] = 1;
	while (1)
	{
		c = max(weishu[index-2],weishu[index-1]);
		jinwei = 0;
		if (7 == index)
		{
			index = index;
		}
		//从低位开始加,有进位就要记住
		for (i = 0; i < c;i++)
		{
			d = fibnum[index-2][i] + fibnum[index-1][i] + jinwei;
			jinwei = 0;
			if (d <= 9)
			{
				fibnum[index][i] = d;
			}
			else
			{
				fibnum[index][i] = d - 10;
				jinwei = 1; 
			}
		}
		weishu[index] = c;
		//最后加过来,看是否有进位
		if (jinwei>0)
		{
			fibnum[index][c] = jinwei;
			weishu[index] = c+1;
		}

		if (index>= 500) break;


		index += 1;

	}
	return;
}


int x = 0;

/* 假设 存在的数 x   考察的区间为[a , b]需要注意的 又这么几种情况
   a < b < x
   a < b = x
   a = b < x 
   a = b = x 
   x = a < b 
   x < a = b
   x < a < b*/

int findnew(int s[], int n)
{
	int k;
	for (int i = 0; i <= 498; i++)
	{
		if (weishu[i] < n)
			continue;
		if (weishu[i] == n)
		{
			int flag = 0;
			for (k = n - 1; k >= 0; k--)
			{
				if (fibnum[i][k] > s[k])
					return i;
				else
					if (fibnum[i][k] == s[k])
						continue;
					else
					{
						flag = 1;
						break;
					}
			}
			if (flag == 0)
			{
				x++;
				return i;
			}
		}
		if (weishu[i] > n)
			return i;
	}
	return 0;
}


int find(int type) //1-分析第一个数,2-分析第2个数
{
	int num = 0;
	int i = 0;
	int startindex = 0;
	int findflag = 0;
	int j = 0;
	int cmpindex = 0;
	int sameindex = 0;
	
	if (1 == type)
	{
		num = firstweishu;
	}
	else
	{
		num = secondweishu;
	}

	//查找位数从哪个开始
	for (i = 1; i < index;i++)
	{
		if (1 == type)
		{
			if (num == weishu[i])
			{
				startindex = i; //找到了,然后下面开始找index
				break;
			}
		}
		else
		{
			if ((num+1) == weishu[i]) //要多一位
			{
				startindex = i-1; //找到了,然后下面开始找index
				break;
			}
		}
	}

	//start要找个比>=start的
	if (1 == type)
	{
		while (1)
		{
			findflag = 0;

			if (firstweishu < weishu[startindex])
			{
				findflag = 1;
			}
			else
			{
				//从startindex开始找起,从最高位开始比较
				for (i = num - 1; i >= 0; i--)
				{
					if (fibnum[startindex][i] > first[i])
					{
						findflag = 1;  //找到大数
						break;
					}
					else if (fibnum[startindex][i] == first[i]) //数字相同,那要继续比较
					{
						if (i == 0)
						{
							findflag = 1;
						}
						else
						{
							continue;
						}
					}
					else
					{
						//比现在的数小,那就只能break
						break;
					}
				}
			}
					

			if (1 == findflag)
			{
				cmpindex = max(secondweishu, weishu[startindex]);
				//check找到的数是否<end
				for (j = cmpindex-1; j >= 0;j--)
				{
					if (fibnum[startindex][j] < second[j] )
					{
						return startindex; 
					}
				}

				//判断是否==end
				sameindex = 0;
				for (j = cmpindex - 1; j >= 0; j--)
				{
					if (fibnum[startindex][j] == second[j])
					{
						sameindex +=1; 
					}
				}

				if (cmpindex == sameindex) //==end
				{
					return startindex;
				}

				return 0;				
			}
			else
			{
				startindex += 1;
			}
		}
	}
	else
	{
		//end要找个<=end的
		while (1)
		{
			findflag = 0;
			//从startindex开始找起,从最高位开始比较
			if (secondweishu > weishu[startindex])
			{
				return startindex;
			}

			for (i = num - 1; i >= 0; i--)
			{
				if (fibnum[startindex][i] < second[i])
				{
					findflag = 1;  //找到大数
					break;
				}
				else if (fibnum[startindex][i] == second[i]) //数字相同,那要继续比较
				{
					if (i == 0)
					{
						findflag = 1;
					}
					else
					{
						continue;
					}
				}
				else
				{
					//比现在的数大,那就只能break
					break;
				}
			}

			if (1 == findflag)
			{
				return startindex;
			}
			else
			{
				startindex -= 1;
			}
		}
	}

}

int main()
{
	freopen("input.txt","r",stdin);
	int index1 = 0;
	int index2 = 0;
	int nn = 0;
	int bb = 0;
	int i = 0;
	int l = 0;
	int k = 0;
	//一共有105位最大,那就求出在105位范围内的fib数
	initfib();
	getfib();
	while ((scanf("%s %s", a, b) != EOF && (a[0] != '0' || b[0] != '0')))
	{
		//init();	
		
		parse(); //分解输入输出

		//分析输入的长度,上面parse函数已经得到长度了
		//然后从位数开始找起
		index1 = find(1);
		if (0 != index1)
		{
			index2 = find(2);
		}

		if (0 != index1)
		{
			ans = index2 - index1 + 1;
		}
		else
		{
			ans = 0;
		}
		if (0 == ans)
		{
			ans = ans;
		}
		printf("%d\n",ans);	

		//下面注释的是第2种做法可以AC
		/*firstweishu = strlengths(a);
		secondweishu = strlengths(b);
		x = 0;
		index1 = findnew(first, firstweishu);
		nn = x;
		x = 0;
		index2 = findnew(second, secondweishu);
		bb = x;
		if (nn == 1 && bb == 1)
		{			
			printf("%d\n", index2 - index1 + 1);
			continue;
		}
		else if (nn == 1 && bb == 0)
			printf("%d\n", index2 - index1 );
		else
			if (nn == 0 && bb == 1)
				printf("%d\n", index2 - index1 + 1);
			else
				printf("%d\n", index2 - index1);*/
		//initmatrix();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值