POJ 2413 How many Fibs? /HDOJ 1316 How Many Fibs?

题目来源:http://poj.org/problem?id=2413 /  http://acm.hdu.edu.cn/showproblem.php?pid=1316



How many Fibs?
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10742 Accepted: 3979

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<=10 100. 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

Source


题意: 求区间[a,b]  上Fibonacci 数的个数。
题解: 大数(用了压位高精度)+打表
PS: 我下面这个代码要在杭电上提交,编译器得选C++ 才给过 在POJ上G++是可以过的=-=  为此我还在知乎上提问了http://www.zhihu.com/question/27057931/answer/35115406?group_id=527458265756372992
然后找到问题了~~~ pow函数不能随便用啊,,老老实实自己实现吧=-=

AC代码:
#include<iostream>
#include<fstream> 
#include<string>
#include<cmath>
#define carry 100000000
#define maxn 600
using namespace std;
ifstream fin("in.txt");
ofstream fout("t.txt");
#define cin fin
#define cout fout
string num[maxn];
void str2num(string &x, int *num){
	int len = x.size(), pos = 0;
	for (int i = 1; i <= len / 8; i++){
		string temp = x.substr(len - 8 * i, 8);
		for (int i = 0; i<8; i++)
			num[pos] += (temp[7 - i] - '0')*(int)pow(10.0,double(i));
		pos++;
	}
	int left = len % 8;
	if (left){
		for (int i = 0; i < left; i++)
			num[pos] += (x[left - i - 1] - '0')*(int)pow(10.0,double(i));
		pos++;
	}
}
void num2str(int x, string &str){
	int temp[10] = { 0 }, pos = 0;
	while (x){
		temp[pos++] = x % 10;
		x /= 10;
	}
	for (int i = 7; i >= 0; i--)
		str += temp[i] + '0';
}
void Add(string x, string & y, string &z)
{
	string rest = "";
	int num1[maxn] = { 0 }, num2[maxn] = { 0 };
	int len = x.size() > y.size() ? x.size() : y.size();
	str2num(x, num1);
	str2num(y, num2);
	for (int i = 0; i <= len / 8; i++){
		num1[i] += num2[i];
		if (num1[i] >= carry){
			num1[i + 1] += num1[i] / carry;
			num1[i] %= carry;
		}
	}
	int k;
	for (k = len; k>0 && !num1[k]; k--);
	for (; k >= 0; k--) num2str(num1[k], rest);
	z = rest;
}
int cmp(string &x, string &y){
	int len1 = x.size(), len2 = y.size();
	int i;
	for (i = 0; i<len1&&!(x[i] - '0');)i++;
	x = x.substr(i, len1 - i + 1);
	//	cout<<i<<endl;
	for (i = 0; i<len2&&!(y[i] - '0');)i++;
	y = y.substr(i, len2 - i + 1);
	//	cout<<x<<" "<<y<<endl;
	len1 = x.size(), len2 = y.size();
	if (x == y)return 0;
	if (len1>len2)return 1;
	else if (len1<len2)return -1;
	else if (x>y)return 1;
	else return -1;
}
string str1, str2;
int calc(string &x, int left, int right, int dir)
{
	
	int cmpleft = cmp(x, num[left]), cmpright = cmp(x, num[right]), mid = (left + right) / 2;
	if (cmpleft<0){ if (dir)  return left;  else return left - 1; }
	else if (cmpright>0){ if (!dir) return right; else return right +1; }
	else if (!cmpleft)return left;
	else if (!cmpright)return right;
	int cmpmid = cmp(x, num[mid]);
	if (!cmpmid)return mid;
	else if (cmpmid<0)return calc(x, left, mid - 1,dir);
	else return calc(x, mid + 1, right, dir);
}



标准代码AC代码:
#include<iostream>
#include<string>
#include<cmath>
#define carry 100000000
#define maxn 600
using namespace std;
string num[maxn];
int Pow(int x,int y){
	int m=1;
	for(int i=0;i<y;i++)
	m*=x;
	return m;
} 
void str2num(string &x, int *num){
	int len = x.size(), pos = 0;
	for (int i = 1; i <= len / 8; i++){
		string temp = x.substr(len - 8 * i, 8);
		for (int i = 0; i<8; i++)
			num[pos] += (temp[7 - i] - '0')*Pow(10,i);
		pos++;
	}
	int left = len % 8;
	if (left){
		for (int i = 0; i < left; i++)
			num[pos] += (x[left - i - 1] - '0')*Pow(10,i);
		pos++;
	}
}
void num2str(int x, string &str){
	int temp[10] = { 0 }, pos = 0;
	while (x){
		temp[pos++] = x % 10;
		x /= 10;
	}
	for (int i = 7; i >= 0; i--)
		str += temp[i] + '0';
}
void Add(string x, string & y, string &z)
{
	string rest = "";
	int num1[maxn] = { 0 }, num2[maxn] = { 0 };
	int len = x.size() > y.size() ? x.size() : y.size();
	str2num(x, num1);
	str2num(y, num2);
	for (int i = 0; i <= len / 8; i++){
		num1[i] += num2[i];
		if (num1[i] >= carry){
			num1[i + 1] += num1[i] / carry;
			num1[i] %= carry;
		}
	}
	int k;
	for (k = len; k>0 && !num1[k]; k--);
	for (; k >= 0; k--) num2str(num1[k], rest);
	z = rest;
}
int cmp(string &x, string &y){
	int len1 = x.size(), len2 = y.size();
	int i;
	for (i = 0; i<len1&&!(x[i] - '0');)i++;
	x = x.substr(i, len1 - i + 1);
	//	cout<<i<<endl;
	for (i = 0; i<len2&&!(y[i] - '0');)i++;
	y = y.substr(i, len2 - i + 1);
	//	cout<<x<<" "<<y<<endl;
	len1 = x.size(), len2 = y.size();
	if (x == y)return 0;
	if (len1>len2)return 1;
	else if (len1<len2)return -1;
	else if (x>y)return 1;
	else return -1;
}
string str1, str2;
int calc(string &x, int left, int right, int dir)
{
	
	int cmpleft = cmp(x, num[left]), cmpright = cmp(x, num[right]), mid = (left + right) / 2;
	if (cmpleft<0){ if (dir)  return left;  else return left - 1; }
	else if (cmpright>0){ if (!dir) return right; else return right +1; }
	else if (!cmpleft)return left;
	else if (!cmpright)return right;
	int cmpmid = cmp(x, num[mid]);
	if (!cmpmid)return mid;
	else if (cmpmid<0)return calc(x, left, mid - 1,dir);
	else return calc(x, mid + 1, right, dir);
}


int main()
{
	cin.sync_with_stdio(false);
	num[1] = "1"; num[2] = "2";
	for (int i = 3; i<maxn; i++)
		Add(num[i - 1], num[i - 2], num[i]);
	while (cin >> str1 >> str2, str1 != "0" || str2 != "0"){
		int pos1 = calc(str1, 1, maxn - 1,1), pos2 = calc(str2, 1, maxn - 1, 0);
		cout<<pos2-pos1+1<<endl; 
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值