zoukankan      html  css  js  c++  java
  • 一个差生解1642Fibonacci 第 n 项

     

    1642: 【例 2】Fibonacci 第 n 项
    
    时间限制: 1000 ms         内存限制: 524288 KB
    提交数: 70     通过数: 22 
    【题目描述】
    大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2 。
    
    现在问题很简单,输入 nn 和 mm,求 fnmodmfnmodm。
    
    【输入】
    输入 n,mn,m。
    
    【输出】
    输出 fnmodmfnmodm。
    
    【输入样例】
    5 1000
    【输出样例】
    5
    【提示】
    数据范围与提示:
    
    对于 100% 的数据, 1≤n≤2×109,1≤m≤109+101≤n≤2×109,1≤m≤109+10
    1642: 【例 2】Fibonacci 第 n 项

     由于之前也做过几次Fibonacci数列问题,随手翻了下,看到了一本通网站1642:Fibonacci数列第n项。起初并没有注意这个题是在哪个章节,但看了一下题目,感觉不太难,然后就开始做了。上手后,再细看条件,“对于 100% 的数据, 1n2×10^9,1m10^9+10”,这很是要命啊,估计能做到O(n)的时间复杂度都怕是没戏。于是,得思考更高级的时间复杂度算法,初步想到的是O(logn),二分法就是最常见的O(logn)时间复杂度了。那我的想法就集中在f(n)与f(n/2)的关系上了。由于这个题边界条件是两个,f(1)=f(2)=1,估计要直接用f(n/2)表示f(n)是有难度的,还有n可能是一个奇数,也可能是偶数,所以我思考的方向是用两项表示两项:比如用f(3)、f(4)表示f(7)、f(8),再用f(7)、f(8)表示f(15)、f(16)等。为了方便验算,我先求了前面的部分项:f(3)=2,f(4)=3,f(5)=5,f(6)=8,f(7)=13,f(8)=21,f(9)=34,f(10)=55。f(3)=f(2)+f(1),f(4)=f(3)+f(2)=2f(2)+f(1),到这看不出什么特殊性,继续...,f(5)=f(4)+f(3)=2f(3)+f(2), f(6)=f(5)+f(4)=3f(3)+2f(2),有点眉目了,还不明显,再算:f(7)=3f(4)+2f(3),f(8)=3f(5)+2f(4),f(9)=3f(6)+2f(5),f(10)=3f(7)+2f(6),似乎看到f(n+3)=3f(n)+2f(n-1),但不是我们的目标,继续向下:f(8)=5f(4)+3f(3),f(9)=5f(5)+3f(4),f(10)=5f(6)+3f(5)=8f(5)+5f(4),这时可以看到“系数似乎也是数列是的项”,如果是这样,那f(7)=f(4)*f(4)+f(3)*f(3), f(9)=f(4)*f(4)+f(5)*f(5),再验证,没错。偶数呢?f(8)=f(5)*f(4)+f(3)*f(4)=(f(4)+f(3))*f(4)+f(4)*f(3)=f(4)*f(4)+2*f(4)*f(3),f(10)=f(5)*f(5)*2*f(5)*f(4),由此推广可知: f(2n+1)=f(n+1)*f(n+1)+f(n)*f(n),f(2n)=f(n)*f(n)+2*f(n)*f(n-1),二分法基本实现,至于证明,我就不做了,直接上网站提交就知道对大数是否成立了。

        不过,还有一个问题,最初我是直接用递归写的程序,但发现会超时,我做了一个跟踪,发现n到1w的时候运算次数就400W次了,所以不能用,于是我想到了记忆递归,直接开个大数组,n的取值是2X10^9,我开了数组a[2e9],编译就报错,开太大了,只好调到a[2e7],部分记忆,还好,能过。

    #include<iostream>
    using namespace std;
    long long const mxn=20000011;
    long long n,m,a[mxn];
    long long fb(long long n)
    {
        if(n==1||n==2)return 1;
        if(n>=mxn){
            long long t1=fb(n/2)%m,t2;
            if(n%2)t2=fb(n/2+1)%m,t1=(t1*t1+t2*t2)%m;
            else t2=fb(n/2-1),t1=(t1*t1+2*t1*t2)%m;
            return t1;
        }
        else
        {
            if(a[n]==0)
            {
                long long t1=fb(n/2)%m,t2;
                if(n%2)t2=fb(n/2+1)%m,a[n]=(t1*t1+t2*t2)%m;
                else t2=fb(n/2-1),a[n]=(t1*t1+2*t1*t2)%m;
            }
            return a[n];
        }
    }
    int main()
    {
        cin>>n>>m;
        cout<<fb(n);
        return 0;
     } 
    1642源代码

     提交到网站,嘿嘿,过了!

    如有不妥,请指教。

    后来才看了这一部分属于矩阵,然后拿书出来看了原书解答,真心不懂,需要花点时间去啃这块硬骨头了。

     

  • 相关阅读:
    设置标题自适应宽度,动态调整大小
    终止延迟函数
    iOS 关于音频开发
    阻止iOS设备锁屏
    苹果开发——设置iTunes Connect中的Contracts, Tax, and Banking
    【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】
    uibutton 设置title 居左显示
    通过view 获取viewController
    tableview 自动滑动到某一行
    uibutton 设置圆角边框
  • 原文地址:https://www.cnblogs.com/wendcn/p/10548381.html
Copyright © 2011-2022 走看看