EOJ2136 大整数

题目:

The good old fibonacci.

Time Limit:1000MS Memory Limit:65536KB
Total Submit:30 Accepted:10

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 therange [a,b].

Input

The input contains several test cases. Each test case consists of twonon-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 leadingzeros.

Output

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

Sample Input

10 100
1234567890 9876543210
0 0

Sample Output

5
4

题目分析:

     初看这题感觉数据量很大,没有思路,后来看了网上的分析才恍然大悟。其实这是可以仔细分析的。此数列是前两项的累加,所以是成比例增长的。10^100约=2^330;同理本数列只需计算出前一千项内应该可以大于10^100;可以通过大整数的加法,通过代码验证实际上第480项就超过100位了。然后只要通过二分查找就可以得出答案了,由于数据量不大也可以直接遍历。

 

总结:

         本题主要考察大整数的加法和大小比较,(二分查找非必须),真正弄明白了就不难了。

主要是要善于分析问题,不要被问题复杂的表面迷惑。同时在本题我还范了一个很低级的错误,习惯性意味数列第二项是1,其实本题是2,导致狂wa了无数次,以后审题要更仔细,避免惯性思维。

 

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <string>

#include <vector>

#include <map>

#include <algorithm>

 

using namespace std;

 

struct Num                         //大整数类,已经写过多次了。

{

   int num[1000]={};

    Num(){memset(num,0,sizeof(num));}

   Num(const string &s)

    {

       int k=0;

       int len=s.size();

       for(int i=len-1;i>=0;--i)

       {

           num[k++]=(s[i]-'0');

       }

    }

   void print()                          //输出大整数,主要用于测试。

    {

       int i;

       for(i=999;i>=0;--i)

       {

           if(num[i])

                break;

       }

       for(;i>=0;--i)

       {

           printf("%d",num[i]);

       }

       printf("\n");

    }

};

 

Num operator+(const Num &a,const Num &b)      //大整数的加法,通过运算符重载,写起来更//简洁。

{

   Num c;

   int i;

   for(i=0;i<1000;++i)

    {

       c.num[i]=a.num[i]+b.num[i];

    }

   for(i=0;i<999;++i)

    {

       c.num[i+1]+=c.num[i]/10;

       c.num[i]%=10;

    }

   return c;

}

 

int cmp(const Num &a,const Num &b)                                        //比较两个大整数的大小

{

   int i,len_a,len_b;

   for(i=999;i>=0;--i)

    {

       if(a.num[i])

           break;

    }

   len_a=i;

   for(i=999;i>=0;--i)

    {

       if(b.num[i])

           break;

    }

   len_b=i;

   if(len_a>len_b)

       return 1;

   else if(len_a<len_b)

       return -1;

   else

    {

       for(i=len_a;i>=0;--i)

       {

           if(a.num[i]>b.num[i])

                return 1;

           else if(a.num[i]<b.num[i])

                return -1;

       }

    }

   return 0;

}

 

 

int main()

{

   Num f[488];

   int i;

   f[1]={"1"};f[2]={"2"};

   for(i=3;i<488;++i)

       f[i]=f[i-1]+f[i-2];

   string a,b;

   while(cin>>a>>b,a!="0" || b!="0")

    {

       int l=0,r=0;

       Num x={a},y={b};

       for(i=1;i<488;++i)

       {

           if(cmp(f[i],x)>=0)

           {

                l=i;

                break;

           }

       }

       for(i=487;i>=1;--i)

       {

           if(cmp(f[i],y)<=0)

           {

                r=i;

                break;

           }

       }

       if(r>=l)

           cout<<r-l+1<<endl;

       else

           cout<<"0"<<endl;

    }

   return 0;

}

### 关于EOJ中的极坐标排序算法实现 对于极坐标排序,在处理几何问题时经常遇到。通常情况下,极坐标排序涉及到将一系列点按照它们相对于某个固定点的角度大小进行排序。 在具体实现上,可以采用如下方式: 1. **计算角度** 对于每一个点 \((x, y)\),先将其转换成相对原点或者指定中心点的向量表示形式。接着利用反正切函数 `atan2` 来获取该点与正X轴之间的夹角。此操作能够确保即使当 \(y\) 值为负数也能得到正确方向上的角度[^1]。 ```cpp double angle = atan2(y - center_y, x - center_x); ``` 2. **自定义比较器** 接下来创建一个用于标准库 sort 函数的比较器来依据上述计算出来的角度对所有点进行升序排列。如果两个不同位置拥有相同角度,则可以根据距离远近进一步区分先后顺序。 3. **特殊情况考虑** 当存在多个点位于同一直线上时(即具有相等的角度),应该额外加入逻辑判断这些共线点间的前后关系,比如可以通过检测横纵坐标的差值来进行微调。 4. **代码实例** 下面给出一段简单的C++代码片段作为示范,展示了如何基于极坐标系下的角度完成一组二维平面上散乱分布的数据点按顺时针或逆时针方向有序化的过程: ```cpp #include <bits/stdc++.h> using namespace std; struct Point { double x, y; }; bool cmp(const Point &a, const Point &b){ // 计算两点到原点(或其他选定参照物)连线所形成的角度 double angA = atan2(a.y, a.x), angB = atan2(b.y, b.x); // 如果角度相等则根据离起点的距离决定次序 if (fabs(angA - angB) < 1e-9) return hypot(a.x,a.y)<hypot(b.x,b.y); // 否则直接对比角度大小 return angA<angB; } int main(){ vector<Point> points={{...}};//初始化数据集 // 调用sort并传入自定义cmp规则 sort(points.begin(),points.end(),cmp); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值