题意
{
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
思路
Fibonomial coefficients+常系数线性递推
由于在
m
o
d
=
1000000000
mod=1000000000
mod=1000000000下
5
5
5的二次剩余不存在,所以不能变为通项的那种方法来做。
那我们可以换一种思路,易知在模意义下斐波那契数列的循环节和次幂的循环节是一样的,原数是循环的那这个数的次幂也是循环的。但是 m o d mod mod太大了,也可以直接去找循环节,直接去找的循环节为1500000000,对于计算答案来说没有什么贡献。但有
m o d = 1000000000 = 2 9 ∗ 5 9 = 512 ∗ 1953125 mod=1000000000=2^9*5^9=512*1953125 mod=1000000000=29∗59=512∗1953125
我们可以求出在模
512
512
512下的
a
1
=
∑
i
=
0
n
f
i
m
%
512
a_1=\sum_{i=0}^{n}f_{i}^m\ \% \ 512
a1=∑i=0nfim % 512和在模
1953125
1953125
1953125下
a
2
=
∑
i
=
0
n
f
i
m
%
1953125
a_2=\sum_{i=0}^{n}f_{i}^m\ \% \ 1953125
a2=∑i=0nfim % 1953125,那么我们就可以得到同余方程组
{
x
≡
a
1
m
o
d
  
512
x
≡
a
2
m
o
d
  
1953125
\left\{\begin{matrix} x\equiv a_1 \mod 512\\ x\equiv a_2 \mod 1953125 \end{matrix}\right.
{x≡a1mod512x≡a2mod1953125
对于这个同余方程组我们套一个中国剩余定理
(
C
R
T
)
(CRT)
(CRT)就可以得到最终
m
o
d
  
1000000000
\mod 1000000000
mod1000000000的答案了
下面我再说一下怎么求解
a
1
a_1
a1和
a
2
a_2
a2
我们先找一下斐波那契数列对于
512
512
512和
1953125
1953125
1953125的循环节,由于这两个数都不大,直接用for循环就可以找到,我们得到的循环节分别是
l
o
o
p
1
=
768
loop_1=768
loop1=768,
l
o
o
p
2
=
7812500
loop_2=7812500
loop2=7812500
我们存下在模
512
512
512和
1953125
1953125
1953125下的斐波那契数列的
m
m
m次幂的和,由于存在循环节所以,斐波那契数列的
m
m
m次幂的和也是同样在
768
768
768,
7812500
7812500
7812500循环的,所以我们前缀和只用存到
768
768
768,
7812500
7812500
7812500就够了记为
s
u
m
1
[
768
]
,
s
u
m
2
[
7812500
]
sum1[768],sum2[7812500]
sum1[768],sum2[7812500]。
对于给你的
n
n
n,由于前缀和在
768
768
768,
7812500
7812500
7812500是重复的,那么答案由两部分构成一部分是重复完整的循环,另一部分就是最后一段多出来的部分,即
a
1
=
(
n
768
∗
s
u
m
1
[
768
]
+
s
u
m
1
[
n
%
768
]
)
%
m
o
d
a_1=(\frac{n}{768}*sum1[768]+sum1[n\%768])\% mod
a1=(768n∗sum1[768]+sum1[n%768])%mod
a
2
=
(
n
7812500
∗
s
u
m
1
[
7812500
]
+
s
u
m
1
[
n
%
7812500
]
)
%
m
o
d
a_2=(\frac{n}{7812500}*sum1[7812500]+sum1[n\%7812500])\% mod
a2=(7812500n∗sum1[7812500]+sum1[n%7812500])%mod
然后套用中国剩余定理就可以了
p
s
:
ps:
ps:由于同余式有
a
≡
b
m
o
d
  
p
→
a
≡
b
m
o
d
  
d
a\equiv b \mod p\rightarrow a\equiv b \mod d
a≡bmodp→a≡bmodd其中
d
∣
p
d|p
d∣p,所以我们在做快速幂和求幂次前缀和还有斐波那契数列的时候都可以模上
m
o
d
=
1000000000
mod=1000000000
mod=1000000000,又有模数都一样了之后前缀和与斐波那契数列只用开一个数组就可以得到答案了
#include<bits/stdc++.h>
using namespace std;
const int l1=768;
const int l2=7812500;
const int MOD=1e9;
long long m[]= {512,1953125};
long long f[l2+5];
long long sum[l2+5];
long long quickmod(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1)
ans=ans*a%MOD;
b>>=1;
a=a*a%MOD;
}
return ans;
}
void exgcd(long long a1,long long b,long long &x,long long &y)
{
if(b==0)
{
x=1;
y=0;
return ;
}
exgcd(b,a1%b,x,y);
long long t=x;
x=y;
y=t-(a1/b)*y;
}
long long CRT(long long a[],long long m[],int n)
{
long long M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];
}
for(int i=0; i<n; i++)
{
t=M/m[i];
exgcd(t,m[i],x,y);
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}
int main()
{
int n,_m;
scanf("%d%d",&n,&_m);
f[0]=0;
f[1]=sum[1]=1;
for(int i=2; i<l2+5; i++)
{
f[i]=(f[i-1]+f[i-2])%MOD;
sum[i]=(sum[i-1]+quickmod(f[i],_m))%MOD;
}
long long a[2];
a[0]=((n/l1)*sum[l1]+sum[n%l1])%MOD;
a[1]=((n/l2)*sum[l2]+sum[n%l2])%MOD;
long long ans=CRT(a,m,2);
printf("%lld\n",ans);
return 0;
}