题意
{
f
0
=
0
f
1
=
1
f
n
=
f
n
−
1
+
f
n
−
2
,
n
≥
2
\left\{\begin{matrix} f_0=0\\ f_1=1\\ f_n=f_{n-1}+f_{n-2},n\geq 2 \end{matrix}\right.
⎩⎨⎧f0=0f1=1fn=fn−1+fn−2,n≥2
给你
n
n
n和
m
m
m求
∑
i
=
0
n
f
i
m
%
1000000000
\sum_{i=0}^{n}f_{i}^m \ \% 1000000000
i=0∑nfim %1000000000
1
≤
n
≤
1
0
9
,
1
≤
m
≤
1000
1\leq n\leq 10^9,1\leq m \leq 1000
1≤n≤109,1≤m≤1000
思路
介绍了循环节的做法
现在我们用官方题解的方法来做这道题
已知
f
n
=
f
n
−
1
+
f
n
−
2
f_{n}=f_{n-1}+f_{n-2}
fn=fn−1+fn−2即
f
n
−
f
n
−
1
−
f
n
−
2
=
0
f_{n}-f_{n-1}-f_{n-2}=0
fn−fn−1−fn−2=0
二次幂下的斐波那契的递推式为
f
n
2
−
2
f
n
−
1
2
−
2
f
n
−
2
2
+
f
n
−
3
2
=
0
f_{n}^2-2f_{n-1}^2-2f_{n-2}^2+f_{n-3}^2=0
fn2−2fn−12−2fn−22+fn−32=0
三次幂
f
n
3
−
3
f
n
−
1
3
−
6
f
n
−
2
3
+
3
f
n
−
3
3
+
f
n
−
4
3
=
0
f_{n}^3-3f_{n-1}^3-6f_{n-2}^3+3f_{n-3}^3+f_{n-4}^3=0
fn3−3fn−13−6fn−23+3fn−33+fn−43=0
这个次幂的递推式前面的系数是什么呢。
这个系数的绝对值就是Fibonomial coefficients
这个Fibonomial coefficients是什么呢
我们知道二项式系数有
C
n
m
=
n
(
n
−
1
)
(
n
−
2
)
(
n
−
3
)
⋯
(
n
−
m
+
1
)
1
∗
2
∗
3
∗
⋯
∗
m
C_{n}^{m}=\frac{n(n-1)(n-2)(n-3)\cdots(n-m+1)}{1*2*3*\cdots*m}
Cnm=1∗2∗3∗⋯∗mn(n−1)(n−2)(n−3)⋯(n−m+1)
而这个Fibonomial coefficients就是类似于二项式系数的方法只是把数的乘积改为斐波那契数的乘积了
即
A
n
m
=
f
n
∗
f
n
−
1
∗
f
n
−
2
∗
⋯
∗
f
n
−
m
+
1
f
1
∗
f
2
∗
f
3
∗
⋯
∗
f
m
A_{n}^m=\frac{f_{n}*f_{n-1}*f_{n-2}*\cdots*f_{n-m+1}}{f_{1}*f_{2}*f_{3}*\cdots*f_{m}}
Anm=f1∗f2∗f3∗⋯∗fmfn∗fn−1∗fn−2∗⋯∗fn−m+1
打个表出来就是
n
∖
m
0
1
2
3
4
5
6
7
0
:
1
1
:
1
1
2
:
1
1
1
3
:
1
2
2
1
4
:
1
3
6
3
1
5
:
1
5
15
15
5
1
6
:
1
8
40
60
40
8
1
7
:
1
13
104
260
260
104
13
1
\begin{matrix} n \setminus m & 0 &1 &2 &3 &4 &5&6&7\\ 0: & 1 \\ 1: & 1 &1 \\ 2: & 1& 1 &1 \\ 3:& 1 & 2 & 2 & 1 \\ 4: & 1 & 3 & 6 & 3 &1 \\ 5:& 1& 5 & 15 & 15 & 5 &1 \\ 6:&1&8&40&60&40&8&1\\ 7:&1&13&104&260&260&104&13&1 \end{matrix}
n∖m0:1:2:3:4:5:6:7:01111111111123581321261540104313156026041540260518104611371
结合到原题上会发现如果要求的是
k
k
k次幂的求和,那么递推式全移到左边所有系数的绝对值就是这里的
k
+
1
k+1
k+1行
根据
o
e
i
s
oeis
oeis中的公式这个Fibonomial coefficients有如下的递推公式
A
n
k
=
f
n
−
k
−
1
∗
A
n
−
1
k
−
1
+
f
k
+
1
∗
A
n
−
1
k
A_{n}^{k}=f_{n-k-1}*A_{n-1}^{k-1}+f_{k+1}*A_{n-1}^k
Ank=fn−k−1∗An−1k−1+fk+1∗An−1k和杨辉三角的递推公式差不多
但是这里是绝对值的系数。我们要的是有符号的系数那就是 Signed Fibonomial triangle
根据
o
e
i
s
oeis
oeis中的说法有
A
n
m
=
(
−
1
)
⌊
m
+
1
2
⌋
A
n
m
A_{n}^{m}=(-1)^{\left \lfloor \frac{m+1}{2} \right \rfloor}A_{n}^{m}
Anm=(−1)⌊2m+1⌋Anm
那么我们可以打表得到斐波那契数列
m
m
m次的递推式的系数即
A
m
+
1
0
f
n
m
+
A
m
+
1
1
f
n
−
1
m
+
A
m
+
1
2
f
n
−
2
m
+
⋯
+
A
m
+
1
m
+
1
f
n
−
m
−
1
m
=
0
A_{m+1}^{0}f_n^{m}+A_{m+1}^{1}f_{n-1}^m+A_{m+1}^{2}f_{n-2}^m+\cdots+A_{m+1}^{m+1}f_{n-m-1}^m=0
Am+10fnm+Am+11fn−1m+Am+12fn−2m+⋯+Am+1m+1fn−m−1m=0
有了递推式后,我们最后要求的是和而不是
f
n
m
f_{n}^m
fnm,那怎么求解呢。这个时候就有一个技巧了,为了容易表示我们把原式变成
a
0
f
n
+
a
1
f
n
−
1
+
a
2
f
n
−
2
+
⋯
+
a
m
+
1
f
n
−
m
−
1
=
0
a_0f_n+a_1f_{n-1}+a_2f_{n-2}+\cdots+a_{m+1}f_{n-m-1}=0
a0fn+a1fn−1+a2fn−2+⋯+am+1fn−m−1=0
已知
a
0
a_0
a0恒为
1
1
1有
f
n
=
−
(
a
1
f
n
−
1
+
a
2
f
n
−
2
+
⋯
+
a
m
+
1
f
n
−
m
−
1
)
f_n=-(a_1f_{n-1}+a_2f_{n-2}+\cdots+a_{m+1}f_{n-m-1})
fn=−(a1fn−1+a2fn−2+⋯+am+1fn−m−1)
又有
f
n
=
S
n
−
S
n
−
1
f_n=S_n-S_{n-1}
fn=Sn−Sn−1,其中
S
n
=
∑
i
=
1
n
f
i
S_{n}=\sum_{i=1}^nf_i
Sn=∑i=1nfi,可以将这条式子带入有
S
n
−
S
n
−
1
=
−
(
a
1
(
S
n
−
1
−
S
n
−
2
)
+
a
2
(
S
n
−
2
−
S
n
−
3
)
+
⋯
+
a
m
+
1
(
S
n
−
m
−
1
−
S
n
−
m
−
2
)
)
S_n-S_{n-1}=-(a_1(S_{n-1}-S_{n-2})+a_2(S_{n-2}-S_{n-3})+\cdots+a_{m+1}(S_{n-m-1}-S_{n-m-2}))
Sn−Sn−1=−(a1(Sn−1−Sn−2)+a2(Sn−2−Sn−3)+⋯+am+1(Sn−m−1−Sn−m−2))
整理有
S
n
=
(
1
−
a
1
)
S
n
−
1
+
(
a
1
−
a
2
)
S
n
−
2
+
(
a
2
−
a
3
)
S
n
−
3
+
⋯
+
(
a
m
−
a
m
+
1
)
S
n
−
m
−
1
+
a
m
+
1
S
n
−
m
−
2
S_n=(1-a_1)S_{n-1}+(a_1-a_2)S_{n-2}+(a_2-a_3)S_{n-3}+\cdots+(a_{m}-a_{m+1})S_{n-m-1}+a_{m+1}S_{n-m-2}
Sn=(1−a1)Sn−1+(a1−a2)Sn−2+(a2−a3)Sn−3+⋯+(am−am+1)Sn−m−1+am+1Sn−m−2
这就是一个常系数线性递推了,由于
m
≤
1000
m\leq 1000
m≤1000,所以矩阵快速幂就不行了,我们用优化的
O
(
m
2
l
o
g
(
n
)
)
O(m^2log(n))
O(m2log(n))的常系数线性递推的板子就可以了
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e3+5;
const int mod=1000000000;
int n,m,a[N],h[N],c[N],b[N],tmp[N<<1];
long long A[N][N];
long long f[N];
void get_A()
{
f[0]=0;
f[1]=1;
for(int i=2; i<N; i++)
f[i]=(f[i-1]+f[i-2])%mod;
for(int i=0; i<N; i++)
A[i][0]=A[i][i]=1;
for(int i=1; i<N; i++)
{
for(int j=1; j<i; j++)
{
A[i][j]=(f[i-j-1]*A[i-1][j-1]%mod+f[j+1]*A[i-1][j]%mod)%mod;
}
}
for(int i=0; i<N; i++)
{
for(int j=0; j<=i; j++)
{
if(((j+1)/2)%2)
A[i][j]=-A[i][j];
}
}
}
void mul(int *a1,int *a2)
{
for(int i=0; i<=2*m; i++)tmp[i]=0;
for(int i=0; i<=m; i++)
{
for(int j=0; j<=m; j++)
{
tmp[i+j]=(tmp[i+j]+1ll*a1[i]*a2[j])%mod;
}
}
for(int i=2*m-2; i>=m; i--)
{
for(int j=0; j<m; j++)
{
tmp[i-m+j]=(tmp[i-m+j]+1LL*tmp[i]*a[m-j])%mod;
}
tmp[i]=0;
}
for(int i=0; i<m; i++)a1[i]=tmp[i];
}
void pow(int *a1,int t,int *a2)
{
for(; t; t>>=1)
{
if(t&1)mul(a2,a1);
mul(a1,a1);
}
}
long long quickmod(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b=b>>1;
}
return ans;
}
int main()
{
get_A();
scanf("%d%d",&n,&m);
a[1] = 1;
for (int i = 1; i <= m + 1; i++)
{
a[i]=(a[i]-A[m+1][i]+mod)%mod;
a[i+1]=(a[i+1]+A[m+1][i]+mod)%mod;
}
for(int i=1;i<=m+5;i++)
f[i]=(f[i-1]+quickmod(f[i],m))%mod;
if(n<m)
{
printf("%d\n",f[n]);
return 0;
}
m+=2;
b[1]=1;
c[0]=1;
pow(b,n,c);
int ans=0;
for(int i=0; i<m; i++)
{
ans=(ans+1LL*c[i]*f[i]%mod+mod)%mod;
}
printf("%d\n",ans);
return 0;
}