Power of Fibonacci 斐波那契 + 二次剩余

由hdu多校自闭场衍生出的几题
题目1
求$$sum_{I = 1}^nF_i^k (mod 10^9 + 9)$$
感觉像是矩阵快速幂,其实不是
(F_{n} = frac{(frac{1+sqrt5}{2})^n- (frac{1-sqrt 5}{2})^n}{sqrt 5})

因为(383008016^2 equiv 5(mod 10^9 + 9))

所以(383008016 equiv sqrt 5(mod 10^9+9))

所以把383008016乘以(inv(5, 10^9+9))得到

(frac{sqrt 5}{5} equiv 276601605(mod 10^9+9))

同理

(frac{1 + sqrt 5}{5}equiv 691504013 (mod 10^9+9))

(frac{1 - sqrt 5}{5} equiv 308495997(mod 10^9 + 9))

那么(F_n = 276601605(691504013 ^ n - 308495997 ^ n) ( mod 10^9 + 9))

(S = frac{sqrt 5}{5}, R_1 = frac{1 + sqrt5}{2}, R_2 = frac{1 - sqrt 5}{2})

那么(F_n^m = S^m(R_1^n - R_2^n)^m)

(F_n^m = S^msum_{k = 0} ^m C_m^k(R_1^{nk}R_2^{n(m - k)} * (-1)^{m - k}))

那么对于斐波那契前n项和为(S^msum_{k =0 } ^m[C_m^k(sum_{j = 1}^nR_1^{jk}R_2^{j(m - k)})*(-1)^{m - k}])

注意,如果说mod是其他的值,那么久需要用二次剩余求出该模下5的一个剩余

得到答案后,只需要线性递推出(C(m, i))在mod下的值,以及遍历最外面的循环k,其中内部的小循环是一个等比数列,直接快速幂求即可
时间复杂度(O(mlogn))
在求等比数列前n项时不能直接用求和公式(frac{a_1(q - q^n)}{1 - q}),因为q可能为1


整理一下
(F_{n} = frac{(frac{1+sqrt5}{2})^n- (frac{1-sqrt 5}{2})^n}{sqrt 5})

(F_n^m = (frac{1}{sqrt5})^m[(frac{1+sqrt5}{2})^n - (frac{1 - sqrt5}{2})^n]^m)

(a = (frac{1+sqrt5}{2}),b = (frac{1-sqrt5}{2}))

那么(F_n^m = (frac{1}{sqrt5})^m[a^n - b^n]^m)

二项式展开

(F_n^m = (frac{1}{sqrt5})^msum_{k = 0}^m(-1)^kleft(egin{array}{c} m\kend{array} ight)(a^{m - k}b^k)^n)

(t_k = a^{m - k}b^k)

那么(F_n^m = (frac{1}{sqrt5})^msum_{k = 0}^m(-1)^k left(egin{array}{c} m\kend{array} ight)t_k^n)

那么(sum_{i = 1}^nF_i^m = (frac{1}{sqrt 5})^msum_{k = 0}^m(-1)^kleft(egin{array}{c} m\kend{array} ight)sum_{i = 1}^nt_k^i)

[sum_{i = 1}^nF_i^m = (frac{1}{sqrt 5})^msum_{k = 0}^m(-1)^kleft(egin{array}{c} m\kend{array} ight)·left{egin{array}{l}frac{t_k(t_k^i - 1)}{t_k - 1} , t_k ot = 1\n, t_k=1end{array} ight. ]

(mod 10^9+9)情况下,(a equiv 691504013 (mod 10^9+9), bequiv 308495997(mod 10^9 + 9), frac{1}{sqrt5}equiv 276601605(mod 10^9+9))


#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int mod = 1e9 + 9;
const int N = 3e5 + 5; 
ll S = 723398404, R1 = 308495997, R2 = 691504013; 
ll F[N], a[N];
ll pow(ll a, ll b, ll p){
    ll ans = 1; a %= p;
    while(b){
        if(b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}
void ex_gcd(ll a, ll b, ll &d, ll &x, ll &y){
    if(!b) {
        d = a, x = 1, y = 0;
        return;
    }
    ex_gcd(b, a % b, d, y, x);
    y -= x * (a / b);
}
ll cal(ll a, ll b){ //等比数列前n项和
    if(a == 1) return b % mod;
    ll ans = pow(a, b + 1, mod);
    ans = (ans - a + mod) % mod;
    return ans * pow(a - 1, mod - 2, mod) % mod;    
}
ll c[N];
int main(){
    int t;
    scanf("%d", &t);
    while(t--) {
        ll ans = 0;
        ll n, m;
        c[0] = 1;
        scanf("%lld%lld", &n, &m);
        for(int i = 1; i <= m; i++) {// 线性求C(m, i)
            ll d, x, y;
            ex_gcd(i, mod, d, x, y); // 求i对mod的逆元
            x = (x % mod + mod) % mod;
            c[i] = (c[i - 1] * x) % mod;
            c[i] = (c[i] * (m - i + 1)) % mod;
        }
        for(int i = 0; i <= m; i++) {
            ll x = c[i];
            x = x * cal(pow(R1, i, mod) * pow(R2, m - i, mod) % mod, n) % mod;
            x = (x % mod + mod) % mod;
            if((m - i) % 2) ans = (ans - x + mod) % mod;
            else ans = (ans + x + mod) % mod;
        }
        ans = ans * pow(S, m, mod) % mod;
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Emcikem/p/13357401.html