(6755 Fibonacci Sum)
题意
给定 (C, N, K)
规定 (F_{0} = 0, F_{1} = 1, F_{n} = F_{n - 1} + F_{n - 2})
计算
[F_{0}^k + F_{C}^k + F_{2C}^k + ... + F_{CN}^k
]
(1leq N, Cleq 1e18, 1leq Kleq 1e5)
题解
由斐波那契通项公式
[F_{n} = frac{1}{sqrt{5}}((frac{1 + sqrt{5}}{2})^n - (frac{1 - sqrt{5}}{2})^{n})
]
不妨设
[a = frac{1 + sqrt{5}}{2}, b = frac{1 - sqrt{5}}{2}
]
于是得到
[sum_{i = 0}^{N}F_{ic}^k = sum_{i = 0}^{N}(frac{1}{sqrt{5}})^{k}(a^{ic} - b^{ic})^{k}
]
由二项式定理
[(a + b)^n = sum_{i = 0}^{n}C_{n}^{i}a^{n - i}b^{i}
]
展开得到
[sum_{i = 0}^{N}F_{ic}^k = (frac{1}{sqrt{5}})^{k}sum_{i = 0}^{N}sum_{j = 0}^{k}C_{k}^{j}(a^{ic})^{k - j}(-b^{ic})^{j}
]
交换求和顺序,整理得到
[sum_{i = 0}^{N}F_{ic}^k = (frac{1}{sqrt{5}})^{k}sum_{j = 0}^{k}C_{k}^{j}(-1)^{j}sum_{i = 0}^{N}(a^{c(k - j)}cdot b^{cj})^{i}
]
发现第二个循环内部是一个等比数列,设
[q = a^{c(k - j)}cdot b^{cj} = left[a^{k - j}b^{j}
ight]^{c}
]
由求和公式,化简第二层循环(特判 (q = 1))
[sum_{i = 0}^{N}(a^{c(k - j)}cdot b^{cj})^{i} = frac{1 - q^{N + 1}}{1 - q}
]
代入原式得到
[sum_{i = 0}^{N}F_{ic}^k = (frac{1}{sqrt{5}})^{k}sum_{j = 0}^{k}C_{k}^{j}(-1)^{j}(frac{q^{N + 1} - 1}{q - 1})
]
下面考虑优化计算
设
[q_{j} = left[a^{k - j}b^{j}
ight]^{c}, qn_{j} = left[a^{k - j}b^{j}
ight]^{c cdot (N + 1)}
]
则
[q_{j + 1} = left[a^{k - j - 1}b^{j + 1}
ight]^{c}, qn_{j + 1} = left[a^{k - j - 1}b^{j + 1}
ight]^{c cdot (N + 1)}
]
即
[q_{j + 1} = frac{q_{j}}{a^{c}}cdot b^{c}, qn_{j + 1} = frac{qn_{j}}{a^{ccdot (N + 1)}}cdot b^{ccdot (N + 1)}
]
设
[K_{1} = frac{b^c}{a^c}, K_{2} = frac{b^{ccdot (N + 1)}}{a^{ccdot (N + 1)}}
]
则 (q, qn) 可以线性递推
[q_{j + 1} = q_{j}cdot K_{1}, qn_{j + 1} = qn_{j}cdot K_{2}
]
模意义下的指数运算要用欧拉降幂,这是一个 (wa) 点
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define pb push_back
#define dbg(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], "
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL MOD = 1e9 + 9;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MAXN = 1e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
LL qpow(LL a, LL b)
{
b %= MOD - 1;
if(!a) return 0;
LL ans = 1;
while(b) {
if(b & 1) ans *= a, ans %= MOD;
a *= a, a %= MOD, b >>= 1;
}
return ans;
}
LL getInv(LL x) {return qpow(x, MOD - 2);}
LL Add(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return (a + b) % MOD;}
LL Sub(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return (a - b + MOD) % MOD;}
LL Mul(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return a * b % MOD;}
LL Div(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return b * getInv(a) % MOD;}
int t, K;
LL N, C, fac[MAXN], inv_fac[MAXN], q[MAXN], qn[MAXN];
const LL A = 383008016, B = getInv(2), INVA = getInv(A);
const LL a = Mul(Add(1, A), B), b = Mul(Sub(1, A), B);
void ini()
{
fac[0] = 1;
for(int i = 1; i < MAXN; ++i) fac[i] = Mul(fac[i - 1], i);
inv_fac[MAXN - 1] = getInv(fac[MAXN - 1]);
for(int i = MAXN - 2; i >= 0; --i) inv_fac[i] = Mul(inv_fac[i + 1], i + 1);
}
LL getC(int k, int i)
{
return Mul(fac[k], Mul(inv_fac[i], inv_fac[k - i]));
}
LL getGeoSum(LL Q, LL Qn)
{
LL res = Div(Sub(Q, 1), Sub(Qn, 1));
return res;
}
int main()
{
ini();
scanf("%d", &t);
while(t--) {
scanf("%lld %lld %d", &N, &C, &K);
LL ans = 0;
LL K1 = Div(qpow(a, C), qpow(b, C));
LL K2 = Div(qpow(qpow(a, C), N + 1), qpow(qpow(b, C), N + 1));
q[0] = qpow(qpow(a, K), C);
qn[0] = qpow(q[0], N + 1);
for(int j = 1; j <= K; ++j) {
q[j] = Mul(q[j - 1], K1);
qn[j] = Mul(qn[j - 1], K2);
}
for(int j = 0; j <= K; ++j) {
LL Q = q[j], Qn = qn[j];
LL Com = getC(K, j);
LL flag = j % 2 ? -1 : 1;
LL sum1 = Mul(Com, flag), sum2 = 0;
if(Q == 1) sum2 = Mul(sum1, Add(N, 1));
else sum2 = Mul(sum1, getGeoSum(Q, Qn));
ans = Add(ans, sum2);
}
LL co = qpow(INVA, K);
ans = Mul(ans, co);
printf("%lld
", ans);
}
return 0;
}
/*
3
5 1 1
2 1 2
948667308466040306 674466112463401647 84933
*/