2020多校Fibonacci Sum


Fibonacci Sum题目难易度:简単(しかし私はしていません)まずデータnを见て、kはすべて10^18时间の复雑度はO(n)がほとんどなくて、マトリックス乗算pass.今問題を解決して、多くの問題解の参考を探しました.この大物の考えが一番はっきりしていると思います.リンクを添付して自分で振り返ってコメントを追加します.
#include 
using namespace std;
const int MAXN = 1e5 + 10;
const long long mod = 1e9 + 9;
long long fac[MAXN], inv[MAXN];
long long fastpow(long long a, long long b) {
    long long ans = 1;
    a %= mod;
    while (b) {
        if (b & 1)ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
void Init() {
    fac[0] = inv[0] = 1;
    for (int i = 1; i < MAXN; i++) {
        fac[i] = fac[i - 1] * i % mod;//    
        inv[i] = fastpow(fac[i], mod - 2);//    
    }
}

long long Solve(long long n, long long c, long long k) {
    long long ans = 0;
    long long A = fastpow(691504013, c % (mod - 1)), B = fastpow(308495997, c % (mod - 1));
    long long a = 1, b = fastpow(B, k), ib = fastpow(B, mod - 2);
    for (int i = 0; i <= k; i++) {
        long long x = a * b % mod;//  ,       
        long long C = fac[k] * inv[i] % mod * inv[k - i] % mod;//   
        long long sum = x * (fastpow(x, n % (mod - 1)) - 1 + mod) % mod * fastpow(x - 1, mod - 2) % mod;//    
        if (x == 1) sum = n % mod;
        if ((k - i) & 1) ans -= sum * C % mod;//      
        else ans += sum * C % mod;
        ans %= mod;
        a = a * A % mod;//            ,         ,         
        b = b * ib % mod;
    }
    long long num = fastpow(383008016ll, mod - 2);
    ans = ans * fastpow(num, k) % mod;//         
    ans = (ans % mod + mod) % mod;
    return ans;
}

int main() {
    int t;
    long long n, k, c;
    Init();
    scanf("%d", &t);
    while (t--) {
        scanf("%lld%lld%lld", &n, &c, &k);
        printf("%lld
", Solve(n, c, k)); } return 0; }