1. 程式人生 > 實用技巧 >Fibonacci Sum - 斐波那契 + 二次剩餘

Fibonacci Sum - 斐波那契 + 二次剩餘

傳送門
用之前的方法做,卡常數了

\[\sum_{i = 0}^kF_{ic}^k (\mod 10^9+9) \]

\[=\left(\frac{1}{\sqrt{5}}\right)^{k} \sum_{i=0}^{k}(-1)^{i}\left(\begin{array}{l}k \\ i\end{array}\right) \cdot\left\{\begin{array}{c}\frac{t_{i}^{N+1}-1}{t_{i}-1}, \quad t_{i} \neq 1 \\ N+1, \quad t_{i}=1\end{array}\right. \]

\(a_c = (\frac{1+\sqrt5}{2})^c, b_c = (\frac{1-\sqrt5}{2})^c\)

\(t_i = a_c^{k - i}b_c\)

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int mod = 1e9 + 9;
const int N = 2e5 + 5; 
ll B = 308495997, A = 691504013, S = 276601605; 
ll pow(ll a, ll b, ll p){
    ll ans = 1; a %= p; b %= (mod - 1);
    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 fac[N], invfac[N];
void init(){
    fac[0] = 1;
    for(int i = 1; i <= 1e5; i++)
        fac[i] = fac[i - 1] * i % mod;
    invfac[100000] = pow(fac[100000], mod - 2, mod);
    for(int i = 1e5; i >= 1; i--)
        invfac[i - 1] = invfac[i] * i % mod;
}
ll comb(ll n, ll m){
    return n >= m ? fac[n] * invfac[n - m] % mod * invfac[m] % mod: 0;
}
ll cal(ll a, ll n){ // 求等比數列前n項和
    if(a == 1) return (n + 1) % mod;
    ll ans = (pow(a, (n + 1) % (mod - 1), mod) - 1 + mod) % mod;
    return ans * pow((a - 1 + mod) % mod, mod - 2, mod) % mod;
}
void solve(){
    ll n, c, k;
    scanf("%lld%lld%lld", &n, &c, &k);
    ll ans = 0;
    ll AA = pow(A, c % (mod - 1), mod); 
    ll BB = pow(B, c % (mod - 1), mod);
    ll a = 1, b = pow(BB, k, mod);
    ll invB = pow(BB, mod - 2, mod);
    for(int j = 0; j <= k; j++) {
        ll x = a * b % mod;
        x = cal(x, n); //等比數列
        if((k - j) & 1) x = (x == 0 ? x : mod - x);
        ans = (ans + comb(k, j) * x % mod) % mod;
        a = a * AA % mod; // 線性求a
        b = b * invB % mod; // 線性求b
    }
    ans = ans * pow(S, k, mod) % mod;
    printf("%lld\n", ans);
}
int main(){
    init();
    int t;
    scanf("%d", &t);
    while(t--) solve();
    return 0;
}