题意
求 $displaystyle sum_{i=1}^n F_i^m $,($1 leq nleq 10^9,1 leq mleq 10^3$),答案对 $10^9$ 取模。
分析
显然,斐波那契数列在模意义下是有循环节的。
模 $10^9$ 本身的循环节为 $150000000$,还是很大,没意义。
设答案为求和的结果为 $ans$,根据中国剩余定理,要求 $ans \% p$,可先求 $ans \% p_1$ 和 $ans \% p_2$(其中 $p_1p_2 = p$,且 $p_1,p_2$ 互素),然后再合并回去。
设斐波那契数列模 $p$ 时的循环节长度为 $loop(p)$,$10^9 = 2^9 cdot 5^9$,易知 $loop(512)=768$,$loop(1953125)=7812500$。
模数只拆成了两部分,甚至不用上中国剩余定理的模板。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll p = 1e9; const ll p1 = 512, loop1 = 768, inv_p1 = 1537323; const ll p2 = 1953125, loop2 = 7812500, inv_p2 = 109; ll n, m; ll qpow(ll a, ll b, ll p) { ll ret = 1; while(b) { if(b&1) ret = ret * a % p; a = a * a % p; b >>= 1; } return ret; } ll fi(ll n, ll m, ll loop, ll p) { if(n == 1) return 1; if(n == 2) return 2; ll yu = n % loop; ll ret = 2, tmp = 0; if(yu == 1) tmp=1; if(yu == 2) tmp=2; ll a=1, b=1, c; for(int i = 3;i <= loop;i++) { c = (a+b) % p; a = b; b = c; ret = (ret + qpow(c, m, p)) % p; if(i == yu) tmp = ret; } return (ret * (n / loop) % p + tmp) % p; } int main() { scanf("%lld%lld", &n, &m); ll ans1 = fi(n, m, loop1, p1); ll ans2 = fi(n, m, loop2, p2); ll ans = (ans1 * p2 %p * inv_p2 %p + ans2 * p1 % p * inv_p1 %p) % p; printf("%lld ", ans); }
参考链接:https://blog.csdn.net/ACdreamers/article/details/10983813