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

由hdu多校自闭场衍生出的几题
题目1
求$$\sum_{I = 1}nF_ik (\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^m\sum_{k = 0} ^m C_m^k(R_1^{nk}R_2^{n(m - k)} * (-1)^{m - k})\)

那么对于斐波那契前n项和为\(S^m\sum_{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})^m\sum_{k = 0}^m(-1)^k\left(\begin{array}{c} m\\k\end{array}\right)(a^{m - k}b^k)^n\)

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

那么\(F_n^m = (\frac{1}{\sqrt5})^m\sum_{k = 0}^m(-1)^k \left(\begin{array}{c} m\\k\end{array}\right)t_k^n\)

那么\(\sum_{i = 1}^nF_i^m = (\frac{1}{\sqrt 5})^m\sum_{k = 0}^m(-1)^k\left(\begin{array}{c} m\\k\end{array}\right)\sum_{i = 1}^nt_k^i\)

\[\sum_{i = 1}^nF_i^m = (\frac{1}{\sqrt 5})^m\sum_{k = 0}^m(-1)^k\left(\begin{array}{c} m\\k\end{array}\right)·\left\{\begin{array}{l}\frac{t_k(t_k^i - 1)}{t_k - 1} , t_k \not = 1\\n, \ \ \ \ \ \ \ \ \ \ t_k=1\end{array}\right. \]

\(\mod 10^9+9\)情况下,\(a \equiv 691504013 (\mod 10^9+9), b\equiv 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\n", ans);
    }
    return 0;
}
posted @ 2020-07-21 21:01  Emcikem  阅读(240)  评论(0编辑  收藏  举报