zoukankan      html  css  js  c++  java
  • 「POJ 3070」Fibonacci

    在 Fibonacci 数列中,$F_0 = 0, F_1 = 1, F_n = F_{n - 1} + F_{n - 2}$。

    现给定整数 $n, m (0 leq n leq 2 imes 10^9, m=10000)$,求 $F_n mod m$。

    链接

    POJ 3070

    题解

    朴素算法是直接循环递推,时间复杂度为 $O(n)$。

    $F_n$ 变化的形式是线性递推,所以可以用矩阵加速递推。$F_n$ 只与 $F_{n-1}$ 和 $F_{n-2}$ 有关,只需要保存最近的两个 Fibonacci 数,即可得到下一个 Fibonacci 数。

    设 $F(n)$ 表示一个 $1 imes 2 $ 的矩阵,即 $F(n) = egin{bmatrix} F_n & F_{n+1}end{bmatrix}$。

    我们知道 $F(n - 1)$,想要计算出 $F(n)$。因为 $F(n-1) = [F_{n-1}, F_n]$,所以 $F(n)$ 中, $F_n$ 为原矩阵第 $2$ 个数, $F_{n+1}$ 为原矩阵第 $1$ 个数和第 $2$ 个数之和。根据矩阵乘法定义,相当于:
    $$
    F(n)=F(n-1) imes
    egin{bmatrix}
    0 & 1 \
    1 & 1 \
    end{bmatrix}
    $$
    令 $F(0) = egin{bmatrix} 0 & 1end{bmatrix}, A=egin{bmatrix} 0 & 1 \ 1 & 1 \ end{bmatrix}$,那么:
    $$
    F(n)=F(0) imes A^n
    $$
    利用矩阵快速幂求 $A^n$ 即可。

    代码

    #include <cstdio>
    #include <cstring>
    
    typedef long long ll;
    
    const int P = 10000;
    
    struct Matrix{
    	ll f[5];
    	ll a[5][5];
    	ll t[5][5];
    
    	void mulMatrix() {
    		memcpy(t[0], f, sizeof(f));
    		memset(f, 0, sizeof(f));
    		for (int i = 1; i <= 2; i++) {
    			for (int k = 1; k <= 2; k++) {
    				f[i] = (f[i] + (t[0][k] * a[k][i]) % P) % P;
    			}
    		}
    	}
    
    	void mulSelf() {
    		memcpy(t, a, sizeof(a));
    		memset(a, 0, sizeof(a));
    		for (int i = 1; i <= 2; i++) {
    			for (int j = 1; j <= 2; j++) {
    				for (int k = 1; k <= 2; k++) {
    					a[i][j] = (a[i][j] + (t[i][k] * t[k][j]) % P) % P;
    				}
    			}
    		}
    	}
    
    	void _init(){
    		ll _f[5] = {0, 0, 1};
    		ll _a[5][5] = {
    			{0, 0, 0},
    			{0, 0, 1},
    			{0, 1, 1}
    		};
    		memcpy(f, _f, sizeof(_f));
    		memcpy(a, _a, sizeof(_a));
    	}
    
    	void _main(ll n){
    		_init();
    		while (n) {
    			if (n & 1) mulMatrix();
    			mulSelf();
    			n >>= 1;
    		}
    		printf("%lld
    ", f[1]);
    	}
    };
    
    int main() {
    	ll n;
    	while (scanf("%lld", &n) && n != -1) {
    		Matrix fib;
    		fib._main(n);
    	}
    	return 0;
    }
    
  • 相关阅读:
    [pyqt] 基于特征匹配的动漫头像检索系统(一)
    [python] 简单遗传算法与粒子群算法
    [美化] 博客园美化历程
    [同人] 我的莱昂
    数据结构 结语
    灌水机
    Ubuntu 中linux 编译错误的(-)
    目标抓取全站妹子封面图片全部爬下来以图片标题命名
    Makefile 介绍
    Linux 中的 ~/. 表示的意思
  • 原文地址:https://www.cnblogs.com/lcfsih/p/14391377.html
Copyright © 2011-2022 走看看