2020 Multi-University Training Contest #1 1005 Fibonacci Sum
题意
hdu 6755 Fibonacci Sum
求后面的值。
题解
根据斐波那契通项式
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<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define vi vector<int>
#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);
}
}```