2020多校Fibonacci Sum

Fibonacci Sum
题目难度:简单(可我没做出)
首先看数据n,k都是10^18时间复杂度是O(n)基本就没了,矩阵乘法pass。
现在清题,找了好多份题解参考。觉得这个大佬的思路讲得最清晰。附上链接
方便自己回顾加了点注释

#include <bits/stdc++.h>
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\n", Solve(n, c, k));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Nefeertari/article/details/107512492
sum