兔子

来源:互联网 发布:gentlewoman 知乎 编辑:程序博客网 时间:2024/04/16 17:23

题目大意

求fib(n) mod 10^9+9=k的最小n。

做法

我们知道fib(n)=15[(1+52)n(152)n]
不妨设两个特征根分别为a和b,注意ab=1
根号5在1e9+9下是存在的,设为g,那么问题变为
anbn=gk的最小n。
an(1)nan=gk
a2ngkan(1)n=0
an=gk+(5k2+4(1)n)2
不妨分类讨论n为奇数还是偶数,求出根号后变成bsgs问题(只要求解出某个奇偶性的最小n)。
开根号怎么做?可以求出原根然后bsgs。

#include<cstdio>#include<algorithm>#include<cmath>#include<map>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;map<int,int> s;const int p=1000000009,g=383008016,inv2=(p+1)/2,maxn=1000000+10,gg=13;int fib[maxn];int i,j,k,l,r,t,n,m,q,x,y,z,a,b,ans;bool czy;int qsm(int x,int y){    if (!y) return 1;    int t=qsm(x,y/2);    t=(ll)t*t%p;    if (y%2) t=(ll)t*x%p;    return t;}int bsgs(int a,int b,int f){    if (f==0&&b==1) return 0;    int i,k,t=1,r,ans=-1;    q=floor(sqrt(p));    r=qsm(a,q);    //s.clear();    fo(i,1,q){        t=(ll)t*r%p;        if (!s[t]) s[t]=i;    }    t=1;    fo(i,0,q-1){        //t=qsm(a,i);        r=(ll)b*t%p;        t=(ll)t*a%p;        k=s[r];        if (k){            k=k*q-i;            if (k%2!=f) continue;            if (ans==-1||k<ans) ans=k;        }        //t=(ll)t*a%p;    }    r=qsm(a,q);    t=1;    fo(i,1,q){        t=(ll)t*r%p;        s[t]=0;    }    return ans;}bool pd(int n){    /*x=bsgs(gg,n,0);    if (x==-1) return 0;else return 1;*/    if (qsm(n,(p-1)/2)==1) return 1;else return 0;}int main(){    freopen("rabbit.in","r",stdin);freopen("rabbit.out","w",stdout);    czy=1;    /*fib[0]=0;    fib[1]=1;    fo(i,2,maxn-10) fib[i]=(fib[i-1]+fib[i-2])%p;*/    scanf("%d",&k);    fo(i,0,maxn-9)        if (i>maxn-10||fib[i]==k) break;    if (i<=maxn-10){        printf("%d\n",i);        return 0;    }    ans=-1;    a=(ll)(1+g)*inv2%p;    b=(ll)(1-g)*inv2%p;    l=(ll)5*k%p*k%p*qsm(4,p-2)%p;    m=l-1;    (m+=p)%=p;    if (pd(m)){        x=bsgs(gg,m,0);        x/=2;        z=y=qsm(gg,x);        (y+=(ll)g*k%p*inv2%p)%=p;        (y+=p)%=p;        (a+=p)%=p;        n=bsgs(a,y,1);        if (n!=-1) ans=n;        y=-z;        (y+=(ll)g*k%p*inv2%p)%=p;        (y+=p)%=p;        (a+=p)%=p;        n=bsgs(a,y,1);        if (n!=-1&&(ans==-1||n<ans)) ans=n;    }    m=l+1;    (m+=p)%=p;    if (pd(m)){        x=bsgs(gg,m,0);        x/=2;        z=y=qsm(gg,x);        (y+=(ll)g*k%p*inv2%p)%=p;        (y+=p)%=p;        (a+=p)%=p;        n=bsgs(a,y,0);        if (n!=-1&&(ans==-1||n<ans)) ans=n;        y=-z;        (y+=(ll)g*k%p*inv2%p)%=p;        (y+=p)%=p;        (a+=p)%=p;        n=bsgs(a,y,0);        if (n!=-1&&(ans==-1||n<ans)) ans=n;    }    printf("%d\n",ans);    //printf("%d\n",bsgs(gg,500000001,1));}
原创粉丝点击