根据斐波那契通项式 F ( n ) = 1 5 ( a n − b n ) F(n) = \frac{1}{\sqrt5}(a^n-b^n) F(n)=51(an−bn)
其中 a = 1 + 5 2 a=\frac{1+\sqrt5}{2} a=21+5, b = 1 − 5 2 b=\frac{1-\sqrt5}{2} b=21−5
带入式子可得 S ( n ) = 1 5 k ∑ n = 0 N ( a n c − b n c ) k S(n)=\frac{1}{\sqrt5}^k\sum_{n=0}^N(a^{nc}-b^{nc})^k S(n)=51k∑n=0N(anc−bnc)k
二项式展开得 S ( n ) = 1 5 k ∑ n = 0 N ∑ i = 0 k C k i a n c ( k − i ) b n c i ( − 1 ) i S(n)=\frac{1}{\sqrt5}^k\sum_{n=0}^N\sum_{i=0}^kC_{k}^ia^{nc(k-i)}b^{nci}(-1)^i S(n)=51k∑n=0N∑i=0kCkianc(k−i)bnci(−1)i
去掉n可得 S ( n ) = 1 5 k ∑ i = 0 k ( − 1 ) i C k i a ( n + 1 ) c ( k − i ) b ( n + 1 ) c i − 1 a c ( k − i ) b c i − 1 S(n)=\frac{1}{\sqrt5}^k\sum_{i=0}^k(-1)^iC_{k}^i\frac{a^{(n+1)c(k-i)}b^{(n+1)ci}-1}{a^{c(k-i)}b^{ci}-1} S(n)=51k∑i=0k(−1)iCkiac(k−i)bci−1a(n+1)c(k−i)b(n+1)ci−1
这个时候用二次剩余求出 5 \sqrt{5} 5的mod意义下的值然后求出a,b就已经可以求解了,但是阴险的朝鲜人卡了常数……4个logn的快速幂过不去,意味着要大量优化。
根据通项式可得知分母每次更改的值为 b a c \frac{b}{a}^c abc,分子每次更改的值为 b a n c \frac{b}{a}^{nc} abnc分子起始项为 a c k ( n + 1 ) a^{ck(n+1)} ack(n+1) ,而且 n + 1 n+1 n+1的指数也太大了,所以需要对其欧拉降幂,变为(n+1)%(mod-1) (mod为素数)。分母的起始项为 a c k a^{ck} ack
其他细节看代码吧(比如说很多long long)
#include
#define ll long long
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define pii pair
#define vi vector
#define SZ(x) (int)x.size()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define mod 1000000009
using namespace std;
const int N = 1e5 + 5;
const int v5 = 383008016;
const int v51 = 276601605;
const int a = 691504013;
const int ad = 691504012;//a^-1
const int b = 308495997;
inline int powmod(int a, ll b) {
int res = 1;
a = a % mod;
while(b) {
if(b & 1) res = (ll)res * a % mod;
a = (ll) a * a % mod;
b >>= 1;
}
return res;
}
ll fac[N], inv[N];
void init() {
fac[0] = 1;
for(int i = 1; i < N; i++) {
fac[i] = fac[i - 1] * i % mod;
}
inv[N - 1] = powmod(fac[N - 1], mod - 2);
for(int i = N - 2; i >= 0; i--) {
inv[i] = inv[i + 1] * (i + 1) % mod;
}
}
inline int C(int n, int m) {
if(m > n) {
return 0;
}
if(m == 0) {
return 1;
}
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int main(){
init();
int t;
scanf("%d", &t);
while(t--) {
ll n, c;
int k;
scanf("%lld%lld%d", &n, &c, &k);
int sum = 0;
int add = powmod((ll)ad * b % mod, c);//增加
int n1 = (n + 1) % (mod - 1);//降幂
int n0 = (n + 1) % mod;
int q1 = powmod(a, c);
int q = powmod(q1, k);
int st = powmod(q, n1);
int d1 = powmod(add, n1);
for(int i = 0; i <= k; i++) {
int cnt = C(k, i);
if(i & 1) cnt = mod - cnt;
if(q == 1) {
sum= ((ll)sum + (ll)n0 * cnt % mod) % mod;
}
else
sum = ((ll)sum + (ll)(st - 1 + mod) % mod * powmod(q - 1, mod - 2) % mod * cnt % mod) % mod;
q = (ll)q * add % mod;
st = (ll)st * d1 % mod;
}
printf("%d\n", (ll)sum * powmod(v51, k) % mod);
}
}```