题意
定义Fibonacci 数列:
F 0 = 0 , F 1 = 1 F n = F n − 1 + F n − 2 ( n > 1 ) F_0=0,F_1=1\\ F_n=F_{n-1}+F_{n-2}\ (n>1) F0=0,F1=1Fn=Fn−1+Fn−2 (n>1)
给定整数
N
,
c
,
k
N,c,k
N,c,k,求
∑
n
=
0
N
F
n
c
k
m
o
d
1
0
9
+
9
\sum_{n=0}^NF_{nc}^k\mod{10^9+9}
n=0∑NFnckmod109+9
N
,
c
≤
1
0
18
,
k
≤
1
0
5
N,c\le10^{18},k\le10^5
N,c≤1018,k≤105.
题解
根据Fibonacci数列通项公式
F
n
=
1
5
[
(
1
+
5
2
)
n
−
(
1
−
5
2
)
n
]
\displaystyle F_n=\frac{1}{\sqrt5}\Big[(\frac{1+\sqrt5}{2})^n-(\frac{1-\sqrt5}{2})^n\Big]
Fn=51[(21+5)n−(21−5)n],有
∑
n
=
0
N
F
n
c
k
=
∑
n
=
0
N
(
1
5
)
k
[
(
1
+
5
2
)
n
c
−
(
1
−
5
2
)
n
c
]
k
,
a
c
=
(
1
+
5
2
)
c
,
b
c
=
(
1
−
5
2
)
c
=
(
1
5
)
k
∑
n
=
0
N
∑
i
=
0
k
(
−
1
)
i
(
k
i
)
(
a
c
k
−
i
b
c
i
)
n
,
t
i
=
a
c
k
−
i
b
c
i
=
(
1
5
)
k
∑
i
=
0
k
(
−
1
)
i
(
k
i
)
∑
n
=
0
N
t
i
n
=
(
1
5
)
k
∑
i
=
0
k
(
−
1
)
i
(
k
i
)
⋅
{
t
i
N
+
1
−
1
t
i
−
1
,
t
i
≠
1
N
+
1
,
t
i
=
1
\begin{aligned} \sum_{n=0}^NF_{nc}^k&=\sum_{n=0}^N\Big(\frac{1}{\sqrt5}\Big)^k\Big[(\frac{1+\sqrt5}{2})^{nc}-(\frac{1-\sqrt5}{2})^{nc}\Big]^k,\quad a_c=(\frac{1+\sqrt5}{2})^c,b_c=(\frac{1-\sqrt5}{2})^c\\ &=\Big(\frac{1}{\sqrt5}\Big)^k\sum_{n=0}^N\sum_{i=0}^k(-1)^i{k\choose i}(a_c^{k-i}b_c^i)^n,\quad t_i=a_c^{k-i}b_c^i\\ &=\Big(\frac{1}{\sqrt5}\Big)^k\sum_{i=0}^k(-1)^i{k\choose i}\sum_{n=0}^Nt_i^n\\ &=\Big(\frac{1}{\sqrt5}\Big)^k\sum_{i=0}^k(-1)^i{k\choose i}\cdot\left\{\begin{aligned} \frac{t_i^{N+1}-1}{t_i-1},&\quad t_i\neq 1\\ N+1,&\quad t_i=1 \end{aligned}\right. \end{aligned}
n=0∑NFnck=n=0∑N(51)k[(21+5)nc−(21−5)nc]k,ac=(21+5)c,bc=(21−5)c=(51)kn=0∑Ni=0∑k(−1)i(ik)(ack−ibci)n,ti=ack−ibci=(51)ki=0∑k(−1)i(ik)n=0∑Ntin=(51)ki=0∑k(−1)i(ik)⋅⎩⎪⎨⎪⎧ti−1tiN+1−1,N+1,ti=1ti=1
暴力预处理出
38300801
6
2
≡
61699199
3
2
≡
5
(
m
o
d
1
0
9
+
9
)
383008016^2\equiv616991993^2\equiv5\pmod{10^9+9}
3830080162≡6169919932≡5(mod109+9) ,任取一个作为
5
\sqrt5
5模意义下的值即可。
再求出
a
≡
1
+
5
2
(
m
o
d
1
0
9
+
9
)
,
b
≡
1
−
5
2
(
m
o
d
1
0
9
+
9
)
)
\displaystyle a\equiv\frac{1+\sqrt5}{2}\pmod{10^9+9},b\equiv\frac{1-\sqrt5}{2}\pmod{10^9+9)}
a≡21+5(mod109+9),b≡21−5(mod109+9))。
计算快速幂的时候用
a
b
≡
a
b
m
o
d
P
−
1
(
m
o
d
P
)
a^b\equiv a^{b\mod{P-1}}\pmod{P}
ab≡abmodP−1(modP)降幂优化。
t
i
t_i
ti可以通过
t
i
=
t
i
−
1
⋅
(
b
a
)
c
\displaystyle t_i=t_{i-1}\cdot(\frac ba)^c
ti=ti−1⋅(ab)c递推计算。
时间复杂度
O
(
∑
k
log
P
)
O(\sum k\log P)
O(∑klogP)
const int P = 1e9 + 9, sqrt5 = 383008016, invsqrt5 = 276601605, A = 691504013,
B = 308495997;
inline int FastExp(int a, ll b) {
int x = 1;
for (b %= P - 1; b; b >>= 1, a = (ll)a * a % P)
if (b & 1)
x = (ll)x * a % P;
return x;
}
inline void Solve() {
ll Ans = 0;
int t = FastExp(FastExp(A, k), c),
q = FastExp((ll)B * FastExp(A, P - 2) % P, c);
for (int i = 0; i <= k; ++i, t = (ll)t * q % P)
if (t == 1)
Ans += ((i & 1) ? -1 : 1) * (ll)C(k, i) * ((n + 1) % P) % P;
else
Ans += ((i & 1) ? -1 : 1) * (ll)C(k, i) * (FastExp(t, n + 1) - 1) % P * FastExp(t - 1, P - 2) % P;
Ans = (Ans % P + P) % P * FastExp(invsqrt5, k) % P;
printf("%lld\n", Ans);
}
预处理分块幂
a
n
=
a
S
⌊
n
S
⌋
+
(
n
m
o
d
S
)
=
a
S
⌊
n
S
⌋
⋅
a
n
m
o
d
S
=
f
a
,
1
(
⌊
n
S
⌋
)
⋅
f
a
,
2
(
n
m
o
d
S
)
\displaystyle a^n=a^{S\lfloor\frac{n}{S}\rfloor+(n\mod{S})}=a^{S\lfloor\frac{n}{S}\rfloor}\cdot a^{n\mod{S}}=f_{a,1}(\lfloor\frac{n}{S}\rfloor)\cdot f_{a,2}(n\mod{S})
an=aS⌊Sn⌋+(nmodS)=aS⌊Sn⌋⋅anmodS=fa,1(⌊Sn⌋)⋅fa,2(nmodS),取
S
=
2
15
,
S
2
>
1
0
9
+
9
S=2^{15},S^2>10^9+9
S=215,S2>109+9,将取模和整除转化为位运算。这样快速幂就可以
O
(
1
)
O(1)
O(1)求出。
假设
t
i
≠
1
t_i\neq 1
ti=1,则有
∑
n
=
0
N
F
n
c
k
=
(
1
5
)
k
1
∏
i
=
0
k
(
t
i
−
1
)
∑
i
=
0
k
(
−
1
)
i
(
k
i
)
(
t
i
N
+
1
−
1
)
∏
j
≠
i
(
t
i
−
1
)
\sum_{n=0}^NF_{nc}^k=\Big(\frac{1}{\sqrt5}\Big)^k\frac{1}{\prod\limits_{i=0}^k(t_i-1)}\sum_{i=0}^k(-1)^i{k\choose i}(t_i^{N+1}-1)\prod_{j\neq i}(t_i-1)
n=0∑NFnck=(51)ki=0∏k(ti−1)1i=0∑k(−1)i(ik)(tiN+1−1)j=i∏(ti−1)
预处理出
t
i
−
1
t_i-1
ti−1的前缀积和后缀积,就可以只需要算一次逆元,再特判一下存在
t
i
=
1
t_i=1
ti=1的情况即可。
注意到
a
b
=
−
1
ab=-1
ab=−1,于是有
a
k
−
i
b
i
=
{
(
−
1
)
i
a
k
−
2
i
,
i
≤
k
2
(
−
1
)
k
−
i
b
2
i
−
k
,
i
>
k
2
a^{k-i}b^i= \left\{\begin{aligned} (-1)^ia^{k-2i},&\quad i\le\frac{k}{2}\\ (-1)^{k-i}b^{2i-k},&\quad i>\frac{k}{2} \end{aligned}\right.
ak−ibi=⎩⎪⎪⎨⎪⎪⎧(−1)iak−2i,(−1)k−ib2i−k,i≤2ki>2k
这样替换就可以在求
t
i
t_i
ti和
t
i
N
+
1
t_i^{N+1}
tiN+1时少做几次乘法和取模运算。
时间复杂度
O
(
P
+
∑
k
)
O(\sqrt P+\sum k)
O(P+∑k)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, S = (1 << 15) - 1, P = 1e9 + 9, sqrt5 = 383008016,
invsqrt5 = 276601605, A = 691504013, B = 308495997;
typedef long long ll;
typedef int arr[N];
/*-----------------------------------------------------------------*/
int k;
arr g, pre, suf, fac = {1}, ifac, f_1[2] = {{1}, {1}}, f_2[2] = {{1}, {1}};
ll n, c;
inline int C(int n, int m) {
return n >= m ? (ll)fac[n] * ifac[n - m] % P * ifac[m] % P : 0;
}
inline int FastExp(int a, int b) {
int x = 1;
for (; b; b >>= 1, a = (ll)a * a % P)
if (b & 1)
x = (ll)x * a % P;
return x;
}
inline int BlockExp(int t, int b) {//t=0表示底数为A;t=1表示底数为B
return (ll)f_1[t][b >> 15] * f_2[t][b & S] % P;
}
inline ll Sign(ll x) { return x & 1 ? -1 : 1; }
inline void Solve() {
//prepare
int Sign1 = c & 1, Sign2 = (c & 1) * ((n + 1) & 1);//记录几个特殊指数的奇偶性
c %= P - 1;
ll Ans = 0, n1c = (n + 1) % (P - 1) * c % (P - 1);
for (int i = 0; i <= (k - 1) / 2; ++i)
g[i] = Sign(Sign1 * i & 1) * BlockExp(0, c * (k - 2 * i) % (P - 1)) - 1;
if (!(k & 1))
g[k / 2] = Sign((Sign1 * k / 2) & 1) == 1 ? 1 : -2;
for (int i = k / 2 + 1; i <= k; ++i)
g[i] = Sign(Sign1 * (k - i) & 1) * BlockExp(1, c * (2 * i - k) % (P - 1)) - 1;
pre[0] = 1, suf[k] = 1;
for (int i = 1; i <= k; ++i)
pre[i] = (ll)pre[i - 1] * g[i - 1] % P;
for (int i = k - 1; i >= 0; --i)
suf[i] = (ll)suf[i + 1] * g[i + 1] % P;
//calculate answer
for (int i = 0; i <= (k - 1) / 2; ++i)
Ans += Sign(i) * C(k, i) * (Sign(Sign2 * i) * BlockExp(0, n1c * (k - 2 * i) % (P - 1)) - 1) % P * pre[i] % P * suf[i] % P;
if (!(k & 1)) {
int t = Sign(Sign1 * k / 2);
Ans += Sign(k / 2) * C(k, k / 2) * (t == 1 ? (n + 1) % P : (n + 1) & 1) % P * pre[k] % P * g[k] % P;
}
for (int i = k / 2 + 1; i <= k; ++i)
Ans += Sign(i) * C(k, i) * (Sign(Sign2 * (k - i)) * BlockExp(1, n1c * (2 * i - k) % (P - 1)) - 1) % P * pre[i] % P * suf[i] % P;
Ans = (Ans % P + P) % P * FastExp(invsqrt5, k) % P * FastExp((ll)pre[k] * g[k] % P, P - 2) % P;
printf("%lld\n", (Ans % P + P) % P);
}
int main() {
for (int i = 1; i <= 1e5; ++i)
fac[i] = (ll)fac[i - 1] * i % P;
ifac[100000] = FastExp(fac[100000], P - 2);
for (int i = 1e5; i >= 1; --i)
ifac[i - 1] = (ll)ifac[i] * i % P;
for (int i = 1; i <= S; ++i)
f_2[0][i] = (ll)f_2[0][i - 1] * A % P,
f_2[1][i] = (ll)f_2[1][i - 1] * B % P;
f_1[0][1] = (ll)f_2[0][S] * A % P;
f_1[1][1] = (ll)f_2[1][S] * B % P;
for (int t = 0; t <= 1; ++t)
for (int i = 2; i <= S; ++i)
f_1[t][i] = (ll)f_1[t][i - 1] * f_1[t][1] % P;
scanf("%*d");
while (~scanf("%lld%lld%d", &n, &c, &k))
Solve();
return 0;
}
卡常害人