zoukankan      html  css  js  c++  java
  • Codechef:Fibonacci Number/FN——求通项+二次剩余+bsgs

    题意

    定义 $F_n$ 为

    $$F_n = left{egin{matrix}
    0, n=0\
    1, n=1 \
    F_{n-1} + F_{n-2}, n > 1
    end{matrix} ight.$$

    现给你一个素数 $p$ 和一个非负整数 $C$,你需要最小的非负整数 $n$,使得 $F_n equiv C (mod p)$.

    分析

    因为题目保证 $p mod 10$ 是一个完全平方数,也就是说 $p mod 5$ 等于1或-1,即5是模$p$ 的二次剩余(据说)。

    求出通项,用Cipolla求出5的二次剩余,记为 $c$,并记 $p = frac{1+c}{2}$,

    通项变成

    $${1over c}left(p^n-(-1)^n{1over p^n} ight)equiv apmod{P}$$

    解得

    $$p^nequiv {acpm sqrt{ac+4(-1)^n}over 2}$$

    然后枚举一下 $n$ 的奇偶性,再用BSGS求出 $n$就可以了。

    //我原来的模板好像有问题,这里贴大佬的模板

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define inf 0x7fffffff
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    int P;
    inline int add(R int x,R int y){return 0ll+x+y>=P?0ll+x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
        R int res=1;
        for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
        return res;
    }
    int w,a;
    struct cp{
        int x,y;
        inline cp(R int _x,R int _y):x(_x),y(_y){}
        inline cp operator *(const cp &b)const{
            return cp(add(mul(x,b.x),mul(w,mul(y,b.y))),add(mul(x,b.y),mul(y,b.x)));
        }
    };
    int ksm(R cp x,R int y){
        R cp res(1,0);
        for(;y;y>>=1,x=x*x)if(y&1)res=res*x;
        return res.x;
    }
    int Sqrt(int x){
        if(!x)return 0;
        if(ksm(x,(P-1)>>1)==P-1)return -1;
        while(true){
            a=mul(rand(),rand()),w=dec(mul(a,a),x);
            if(ksm(w,(P-1)>>1)==P-1)return ksm(cp(a,1),(P+1)>>1);
        }
    }
    const int N=262144;
    struct Hash{
        struct eg{int v,nx,w;}e[N];int head[N],tot;
        inline void clr(){memset(head,0,sizeof(head)),tot=0;}
        inline void add(R int v,R int w){e[++tot]={v,head[v&262143],w},head[v&262143]=tot;}
        int query(int x){
            go(x&262143)if(v==x)return e[i].w;
            return -1;
        }
    }mp[2];
    int bsgs(int x,int v,int sgn){
        int m=sqrt(P)+1;mp[0].clr(),mp[1].clr();
        for(R int i=1,res=mul(v,x);i<=m;++i,res=mul(res,x))mp[i&1].add(res,i);
        for(R int i=1,tmp=ksm(x,m),res=tmp;i<=m;++i,res=mul(res,tmp))
            if(mp[(i*m)&1^sgn].query(res)!=-1)return i*m-mp[(i*m)&1^sgn].query(res);
        return inf;
    }
    int c,s,p,inv2,res,rt;
    int main(){
        srand(time(NULL));
    //  freopen("testdata.in","r",stdin);
        for(int T=read();T;--T){
            c=read(),P=read(),s=Sqrt(5),inv2=(P+1)>>1,p=mul(s+1,inv2),c=mul(c,s);
            res=inf;
            rt=Sqrt((1ll*c*c+4)%P);
            if(rt!=-1){
                cmin(res,bsgs(p,mul(add(c,rt),inv2),0)),
                cmin(res,bsgs(p,mul(dec(c,rt),inv2),0));
            }
            rt=Sqrt((1ll*c*c+P-4)%P);
            if(rt!=-1){
                cmin(res,bsgs(p,mul(add(c,rt),inv2),1)),
                cmin(res,bsgs(p,mul(dec(c,rt),inv2),1));
            }
            printf("%d
    ",res==inf?-1:res);
        }
        return 0;
    }

    参考链接:https://www.cnblogs.com/bztMinamoto/p/10664967.html

  • 相关阅读:
    符号表实现(Symbol Table Implementations)
    揭开枚举类的面纱(Unlocking the Enumeration/enum Mystery)
    玩转指针(Playing with Pointers)
    什么是空间复杂度(What is actually Space Complexity ?)
    论困于记忆之物(随笔感言)
    【未有之有】洛依文明相关
    告别
    【未有之有】洛森修炼体系整理
    【未有之有】洛森十三圣人
    复苏
  • 原文地址:https://www.cnblogs.com/lfri/p/11515048.html
Copyright © 2011-2022 走看看