2019牛客暑期多校训练营(第九场)A.The power of Fibonacci

题意:给出n和m,f(n)是斐波那契额数列的第n项,要求计算ans=f(1)^m+f(2)^m+....f(n)^m。即斐波那契额数列前n项的m次幂和。

解法:这题好像有两种解法:一种是循环节+CRT,一种是通项公式,其实这题也可以直接exBM就能AC了。这里我学习的是循环节+CRT的解法https://blog.csdn.net/ftx456789/article/details/99684004。这位博主写得巨好了,我自己总结一下。

大家都知道朴素的斐波那契额数列模一个质数是有循环节的,且这个循环节也比较好找,我们这里猜想其实斐波那契额数列的m次幂和也是要循环节的,但是模数是1e9不是质数很烦。我们把1e9质因数分解

1000000000=2959=5121953125

而如果模数是512和1953125的话是有循环节的,分别是768和7812500,也就是说我们可以快速计算答案在模512下的解以及答案在模1953125下的解。那么我们可以考虑先求出这两个解分别是a1和a2。那么就要如下同余方程组。

ans≡a1 (mod 512)

ans≡a2 (mod 1953125)

那么最后我们用CRT求出这个ans就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL l1=768;  //循环节1 
const LL l2=7812500;  //循环节2 
const int P=1e9;
LL f[l2+10],sum[l2+10];
int n,mi;

LL m[5],a[5];

LL power(LL x,LL p) {
    LL ret=1;
    for (;p;p>>=1) {
        if (p&1) ret=ret*x%P;
        x=x*x%P;
    }
    return ret;
}

LL exgcd(LL a,LL b,LL &x,LL &y) {
    if (b==0) { x=1; y=0; return a; }
        else {
            LL tmp=exgcd(b,a%b,y,x);
            y-=x*(a/b); return tmp;
        }
}

long long work() {
    LL lcm=m[1],X=a[1],t,x,y;
    for (int i=2;i<=2;i++) {
        LL b=(a[i]-X%m[i]+m[i])%m[i];
        LL d=exgcd(lcm,m[i],x,y);   //解这个方程出来t的特解x t=(b/d)*x 
        if (b%d) return -1;
        t=(b/d)*x%m[i];
        X=(X+t*lcm);   //那么X(k)=X(k-1)+tm 
        lcm=lcm*m[i]/d;
        
        X=(X%lcm+lcm)%lcm;
    }
    return X;
}

int main()
{
    cin>>n>>mi;
    f[0]=0; f[1]=1;
    for (int i=2;i<=l2;i++) f[i]=(f[i-1]+f[i-2])%P;
    for (int i=1;i<=l2;i++) sum[i]=(sum[i-1]+power(f[i],mi))%P;
    
    m[1]=512; m[2]=1953125;
    a[1]=((n/l1)*sum[l1]+sum[n%l1])%P;
    a[2]=((n/l2)*sum[l2]+sum[n%l2])%P;
    cout<<work()<<endl;
    return 0;
}

1000000000=2959=5121953125

猜你喜欢

转载自www.cnblogs.com/clno1/p/11566026.html
今日推荐