SPOJ31428 FIBONOMIAL(斐波那契数列)

神鱼推题,必是好题。

前几天刚做过[BJOI2019]勘破神机,于是就会这题了。(BJ人民强啊……%鱼)

首先要求是

$$\sum\limits_{i=0}^nx^if_i$$

应该很明显能想到把 $f_i$ 写成通项公式。

$$f_i=\dfrac{1}{\sqrt{5}}((\dfrac{1+\sqrt{5}}{2})^i-(\dfrac{1-\sqrt{5}}{2})^i)$$

那么带进去:

$$\sum\limits_{i=0}^nx^i\dfrac{1}{\sqrt{5}}((\dfrac{1+\sqrt{5}}{2})^i-(\dfrac{1-\sqrt{5}}{2})^i)$$

$$\dfrac{1}{\sqrt{5}}\sum\limits_{i=0}^nx^i((\dfrac{1+\sqrt{5}}{2})^i-(\dfrac{1-\sqrt{5}}{2})^i)$$

$$\dfrac{1}{\sqrt{5}}(\sum\limits_{i=0}^nx^i(\dfrac{1+\sqrt{5}}{2})^i)-\sum\limits_{i=0}^nx^i(\dfrac{1-\sqrt{5}}{2})^i))$$

$$\dfrac{1}{\sqrt{5}}(\sum\limits_{i=0}^n(\dfrac{1+\sqrt{5}}{2}\times x)^i-\sum\limits_{i=0}^n(\dfrac{1-\sqrt{5}}{2}\times x)^i)$$

扩个系,变成等比数列求和,做完了。

(貌似 $\color{black}{I}\color{red}{tst}$ 大爷用的矩阵快速幂直接切掉了?还是人家神啊……)

复杂度 $O(T\log n)$。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1000000007,inv2=500000004,inv5=400000003;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int t,x;
ll n;
inline int add(int x,int y){return x+y<mod?x+y:x+y-mod;}
inline int sub(int x,int y){return x<y?x-y+mod:x-y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int qpow(int a,int b){
    int ans=1;
    for(;b;b>>=1,a=mul(a,a)) if(b&1) ans=mul(ans,a);
    return ans;
}
struct comp{
    int x,y;
    comp(int xx=0,int yy=0):x(xx),y(yy){}
    comp operator+(comp c){return comp(add(x,c.x),add(y,c.y));}
    comp operator-(comp c){return comp(sub(x,c.x),sub(y,c.y));}
    comp operator*(comp c){return comp(add(mul(x,c.x),mul(5,mul(y,c.y))),add(mul(x,c.y),mul(y,c.x)));}
    comp inv(){
        int t=qpow(sub(mul(x,x),mul(5,mul(y,y))),mod-2);
        return comp(mul(x,t),sub(0,mul(y,t)));
    }
    comp operator/(comp c){return *this*c.inv();}
    bool operator==(comp c){return x==c.x && y==c.y;}
}A(inv2,inv2),B(inv2,mod-inv2),C(0,inv5);
inline comp qpow(comp a,ll b){
    comp ans(1,0);
    for(;b;b>>=1,a=a*a) if(b&1) ans=ans*a;
    return ans;
}
comp calc(comp x,ll n){
    if(x==comp(1,0)) return n+1;
    return (comp(1,0)-qpow(x,n+1))/(comp(1,0)-x);
}
int main(){
    t=read();
    while(t--){
        n=read();x=read()%mod;
        printf("%d\n",(C*(calc(A*comp(x,0),n)-calc(B*comp(x,0),n))).x);
    }
}
View Code

 

posted @ 2019-07-14 21:53  ATS_nantf  阅读(199)  评论(0编辑  收藏  举报