zoukankan      html  css  js  c++  java
  • ZOJ3774_Power of Fibonacci

    求fibonacci数列前N个数的K次方和。

    通项公式:F[n]=((1+sqrt(5))/sqrt(5)-(1-sqrt(5))/sqrt(5))/sqrt(5)。

    有点乱,不过由于可以保证最后的结果是一个整数,所有所有的根号都可以化为整数进行取模和逆元运算。

    首先解二次同余方程,X^2=n (mod M),显然,当n=5的时候,X就可以相当于5了。

    后面的都可以替换掉。

    然后就变成了 F[n]=(A^n+B^n)*C。

    这里通过二项式展开,分别对每一项进行计算,同时又可以发现,每一项求和其实是一个等比数列,于是,就可以直接搞了。

    召唤代码君:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #define M 1000000009
    #define maxn 100100
    typedef long long ll;
    using namespace std;
    
    ll w,a,m,root,inv;
    ll A[maxn],B[maxn];
    ll n,k,ans,cur,now;
    ll AAA,BBB;
    int T;
    
    struct twice{
        ll A,B;
        twice() {}
        twice(ll AA,ll BB) { A=AA,B=BB; }
        void mul(twice T){
            ll aa=A*T.A+(B*T.B)%M*w,bb=A*T.B+B*T.A;
            A=aa%M,B=bb%M;
        }
    };
    
    ll power(ll A,ll B,ll C)
    {
        ll tot=1;
        while (B){
            if (B&1) tot=tot*A%C;
            A=A*A%C,B>>=1;
        }
        return tot;
    }
    
    twice power(twice T,ll y)
    {
        twice C(1,0);
        while (y){
            if (y&1) C.mul(T);
            T.mul(T),y>>=1;
        }
        return C;
    }
    
    ll getroot()
    {
        for (;;){
            a=rand()%M;
            w=(a*a-5+M)%M;
            if (power(w,M/2,M)!=1) break;
        }
        return power(twice(a,1),(M+1)/2).A;
    }
    
    void _init()
    {
        root=getroot();
        A[0]=B[0]=1;
        for (int i=1; i<maxn; i++){
            A[i]=(A[i-1]*i)%M;
            B[i]=power(A[i],M-2,M);
        }
        inv=B[2];
        AAA=(1+root)*inv%M;
        BBB=(M+1-root)*inv%M;
    }
    
    int main()
    {
        _init();
        scanf("%d",&T);
        while (T--){
            scanf("%lld%lld",&n,&k);
            ans=0;
            for (int i=0; i<=k; i++){
                cur=A[k]*(B[i]*B[k-i]%M)%M;
                if (i&1) cur=M-cur;
                now=power(AAA,k-i,M)*power(BBB,i,M)%M;
                if (now>1) now=((power(now,n+1,M)-now)*power(now-1,M-2,M)%M+M)%M;
                    else now=now*n%M;
                (ans+=cur*now)%=M;
            }
            ans=ans*power(root,k*(M-2),M)%M;
            printf("%d
    ",(int)ans);
        }
        return 0;
    }
  • 相关阅读:
    CodeForces Gym 100935G Board Game DFS
    CodeForces 493D Vasya and Chess 简单博弈
    CodeForces Gym 100935D Enormous Carpet 快速幂取模
    CodeForces Gym 100935E Pairs
    CodeForces Gym 100935C OCR (水
    CodeForces Gym 100935B Weird Cryptography
    HDU-敌兵布阵
    HDU-Minimum Inversion Number(最小逆序数)
    七月馒头
    非常可乐
  • 原文地址:https://www.cnblogs.com/lochan/p/3886884.html
Copyright © 2011-2022 走看看