2019牛客暑期多校训练营(第九场)The power of Fibonacci——循环节&&CRT

题意

求 $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

原文地址:https://www.cnblogs.com/lfri/p/11365464.html