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;
}