知识点 -斐波拉契数和线性递推方程取模

知识点 -斐波拉契数和线性递推方程取模

解决问题类型:

斐波那契数列的各种性质

结论:

定义

(1)满足递推方程 F i = F i − 1 + F i − 2 , i ≥ 3 ; F 1 = F 2 = 1 F_{i} = F_{i - 1} + F_{i - 2},i \geq 3;F_{1} = F_{2} = 1 Fi=Fi1+Fi2,i3;F1=F2=1,的数列 { F n } \left\{ F_{n} \right\} {Fn}称为斐波那契数列, F n F_{n} Fn为斐波那契数。

(2)斐波那契数列的通项公式为 F n = 1 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] F_{n} = \frac{1}{\sqrt{5}}\left\lbrack \left( \frac{1 + \sqrt{5}}{2} \right)^{n} - \left( \frac{1 - \sqrt{5}}{2} \right)^{n} \right\rbrack Fn=5 1[(21+5 )n(215 )n]

(3) F n ≡ 276601605 ( 69150401 3 n − 30849599 7 n ) ( m o d   ( 1 0 9 + 9 ) ) F_n≡276601605(691504013^n-308495997^n)(mod\ (10^9+9)) Fn276601605(691504013n308495997n)(mod (109+9))

性质

  • Cassini’s 特征:
    F n − 1 F n + 1 − F n 2 = ( − 1 ) n F_{n-1} F_{n+1} - F_n^2 = (-1)^n Fn1Fn+1Fn2=(1)n
  • 加法规则:
    F n + k = F k F n + 1 + F k − 1 F n F_{n+k} = F_k F_{n+1} + F_{k-1} F_n Fn+k=FkFn+1+Fk1Fn
  • 加法规则推论:
    F 2 n = F n ( F n + 1 + F n − 1 ) F_{2n} = F_n (F_{n+1} + F_{n-1}) F2n=Fn(Fn+1+Fn1)
  • 用上面的结论加归纳法可以证明:对任意正整数 k k k, F n k F_{nk} Fnk F n F_n Fn的倍数.
  • 逆命题也正确: 如果 F m F_{m} Fm F n F_n Fn的倍数,那么m是n的倍数。
  • GCD 特征: G C D ( F m , F n ) = F G C D ( m , n ) GCD(F_m, F_n) = F_{GCD(m, n)} GCD(Fm,Fn)=FGCD(m,n)
  • 斐波那契数列是欧几里得最差情况的输入

斐波那契编码

一个自然数可以被唯一地表示为斐波那契数的和
N = F k 1 + F k 2 + … + F k r N = F_{k_1} + F_{k_2} + \ldots + F_{k_r} N=Fk1+Fk2++Fkr
每次贪心地用最大的斐波那契数去减即可。

模p的循环节

​ 对于递推式 x i = a ∗ x i − 1 + b ∗ x i − 2 x_i = a*x_{i-1}+b*x_{i-2} xi=axi1+bxi2

​ 如果 c = a 2 + 4 b c=a^2+4b c=a2+4b是模 p p p的二次剩余,那么循环节的的长度是 p − 1 p-1 p1的因子,否则,循环节的长度是 ( p + 1 ) ( p − 1 ) (p+1)(p-1) (p+1)(p1)的因子。

模m的循环节

(1)把m素因子分解,即 m = p 1 a 1 ∗ p 2 a 2 ∗ p 3 a 3 . . . ∗ p n a n m = p_1^{a_1} * p_2^{a_2} * p_3^{a_3} ... * p_n^{a_n} m=p1a1p2a2p3a3...pnan

(2)分别计算Fib数模每个 p i a i p_i^{a_i} piai的循环节长度,假设长度分别是 l 1 , l 2 . . . l k l_1,l_2...l_k l1,l2...lk

(3)那么Fib模n的循环节长度 L = l c m ( l 1 , l 2 . . . l k ) L=lcm(l_1,l_2...l_k) L=lcm(l1,l2...lk)

p a p^a pa的循环节要用到定理: 令 G ( p ) G(p) G(p) m o d   p mod\ p mod p的最小循环节,则 G ( p a ) = G ( p ) ∗ p a − 1 G(p^a)= G(p) * p^{a-1} G(pa)=G(p)pa1

十进制矩阵快速幂

M n M^n Mn, n &lt; 1 e 6 n&lt;1e6 n<1e6,M是2乘2的矩阵,时间复杂度为 O ( n ∗ l o g ( 10 ) ∗ k 3 ) O(n*log(10)*k^3) O(nlog(10)k3), 注意1e6已经是上限。

想法是: a 123 = a 3 + a 2 ∗ 10 + a 3 ∗ 100 a^{123}=a^3+a^{2*10}+a^{3*100} a123=a3+a210+a3100

 int len = strlen(str);
    for(int i = len-1;i >= 0;i --) {
        int d = str[i]-'0';
        if(d != 0)  res = res*mat_pow_mod(base,d);
        base = mat_pow_mod(base,10);
    }

复杂度:

例题

牛客多校 -generator 1

给出 x 0 , x 1 , a , b , n , M O D x_0,x_1,a,b,n,MOD x0,x1,a,b,n,MOD 求解公式 x i = a ∗ x i − 1 + b ∗ x i − 2 x_i = a*x_{i-1}+b*x_{i-2} xi=axi1+bxi2

数据范围: 1 ≤ x 0 , x 1 , a , b ≤ 1 0 9 1\le x_0 ,x_1,a,b\le 10^{9} 1x0,x1,a,b109 1 ≤ n ≤ 1 0 1 0 6 , 1 0 9 ≤ M O D ≤ 2 ∗ 1 0 9 1\le n \le 10^{10^6},10^9 \le MOD \le 2*10^9 1n10106,109MOD2109

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.Scanner;
  
public class Main {
    public static int moder;
  
    public static class Matrix{
        public static final int N = 2;
  
        public int[][] a;
  
        public Matrix(){a = new int[2][2];}
  
        public Matrix multiply(Matrix p){
            Matrix ret = new Matrix();
            for (int i = 0; i < N; ++ i){
                for (int k = 0; k < N; ++ k){
                    for (int j = 0; j < N; ++ j){
                        ret.a[i][j] = (int) ((ret.a[i][j] + 1L * a[i][k] * p.a[k][j]) % moder);
                    }
                }
            }
            return ret;
        }
    }
  
    public static void main(String[] args){
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        try {
            String nextLine = bufferedReader.readLine();
            String[] splitted = nextLine.split(" ");
            int x0 = Integer.parseInt(splitted[0]);
            int x1 = Integer.parseInt(splitted[1]);
            int a = Integer.parseInt(splitted[2]);
            int b = Integer.parseInt(splitted[3]);
            nextLine = bufferedReader.readLine();
            splitted = nextLine.split(" ");
            moder = Integer.parseInt(splitted[1]);
            int x = moder;
            BigInteger mod = BigInteger.ONE;
            for (int i = 2; i * i <= x; ++ i){
                if (x % i == 0){
                    while (x % i == 0){
                        mod = mod.multiply(BigInteger.valueOf(i));
                        x /= i;
                    }
                    mod = mod.multiply(BigInteger.valueOf(i - 1));
                    mod = mod.divide(BigInteger.valueOf(i));
                    mod = mod.multiply(BigInteger.valueOf(i + 1));
                }
            }
            if (x > 1){
                mod = mod.multiply(BigInteger.valueOf(x - 1));
                mod = mod.multiply(BigInteger.valueOf(x + 1));
            }
            BigInteger n = BigInteger.ZERO;
            for (int i = 0; i < splitted[0].length(); ++ i){
                n = n.multiply(BigInteger.TEN).add(BigInteger.valueOf(splitted[0].charAt(i) - '0')).mod(mod);
            }
            n = n.add(mod);
            Matrix aa = new Matrix();
            Matrix ret = new Matrix();
            aa.a[0][1] = 1;
            aa.a[1][0] = b;
            aa.a[1][1] = a;
            ret.a[0][0] = ret.a[1][1] = 1;
            for (int i = 0; i < 4000000; ++i) {
                if (n.testBit(i)) {
                    ret = ret.multiply(aa);
                }
                aa = aa.multiply(aa);
            }
            Long ans = (1L * ret.a[0][0] * x0 + 1L * ret.a[0][1] * x1) % moder;
            System.out.println(ans);
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Best KeyBoard

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值