• CF1106F Lunar New Year and a Recursive Sequence(矩阵快速幂+bsgs+exgcd)


    题面

    传送门

    前置芝士

    (BSGS)

    什么?你不会(BSGS)?百度啊

    原根

    对于素数(p)和自然数(a),如果满足(a^xequiv 1pmod{p})的最小的(x)(p-1),那么(a)就是(p)的一个原根

    离散对数

    对于素数(p),以及(p)的一个原根(g),定义(y)(x)的离散对数,当且仅当(g^yequiv xpmod{p}),记(y)(ind_g x)。不难发现原数和离散对数可以一一对应。也不难发现离散对数用(bsgs)就可以求得

    题解

    考虑把题目转化一下,因为(f_{1,...,k-1})都是(1),只有(f_k)不是(1),那么最终的(f_n)一定是形如({f_k}^x)的形式

    那么我们只考虑上面的次数的转移,转移式就可以从一个前面一堆乘起来变成前面一堆加起来的形式。矩阵快速幂求出最终的(f_n)中的次数就行了

    那么就是一个({f_k}^xequiv f_npmod{p})的形式了,其中(x)我们之前已经用矩阵快速幂算出来了

    于是就是关于形如(x^aequiv bpmod{p})形式的方程求解的问题了

    考虑两边取离散对数,学过(NTT)的都知道(998244353)的原根是(3),那么就可以转化成(a imes ind_g xequiv ind_g bpmod{p-1}),用(exgcd)解出(ind_gx),然后代入计算就可以了

    于是问题就解决了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #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 cmax(T&a,const T&b){return a<b?a=b,1:0;}
    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=1,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;
    }
    const int N=105,P=998244353,g=3;
    inline int add(R int x,R int y,R int P){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y,R int P){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y,R int P){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y,R int P){
        R int res=1;
        for(;y;y>>=1,x=mul(x,x,P))if(y&1)res=mul(res,x,P);
        return res;
    }
    int n,kkk,m;
    struct Matrix{
        int a[N][N];
        Matrix(){memset(a,0,sizeof(a));}
        inline int* operator [](const R int &x){return a[x];}
        Matrix operator *(Matrix b){
            Matrix res;
            fp(i,1,kkk)fp(k,1,kkk)fp(j,1,kkk)res[i][j]=add(res[i][j],mul(a[i][k],b[k][j],P-1),P-1);
            return res;
        }
    }A,B;
    Matrix ksm(Matrix x,int y){
        Matrix res;fp(i,1,kkk)res[i][i]=1;
        for(;y;y>>=1,x=x*x)if(y&1)res=res*x;
        return res;
    }
    map<int,int>mp;
    int bsgs(int x){
        int m=sqrt(P)+1;mp.clear();
        for(R int i=0,res=x;i<m;++i,res=1ll*res*g%P)mp[res]=i;
        for(R int i=1,tmp=ksm(g,m,P),res=tmp;i<=m+1;++i,res=1ll*res*tmp%P)
            if(mp.count(res))return i*m-mp[res];
    }
    int exgcd(int a,int b,int &x,int &y){
       if(!b)return x=1,y=0,a;
       int d=exgcd(b,a%b,y,x);
       y-=a/b*x;return d;
    }
    int a,b,c,d,x,y,t,res;
    int main(){
        kkk=read();
        fp(i,1,kkk)B[i][1]=read();
        fp(i,1,kkk-1)B[i][i+1]=1;
        A[1][1]=1;
        n=read(),m=read();
        A=A*ksm(B,n-kkk);
        c=bsgs(m),a=A[1][1],b=P-1;
        d=exgcd(a,b,x,y);
        if(c%d)return puts("-1"),0;
        t=abs(b/d);
        x=(1ll*x*(c/d)%t+t)%t;
    //    printf("%d %d
    ",x,bsgs(m));
        res=ksm(g,x+P-1,P);
        printf("%d
    ",res);
        return 0;
    }
    
  • 相关阅读:
    计算机网络【七】:可靠传输的实现 (tcp窗口滑动以及拥塞控制)【转】
    计算机网络【六】:传输层-TCP概述 【转】
    计算机网络【五】:路由选择协议 【转】
    计算机网络【三】:数据链路层 【转】
    计算机网络【二】:物理层【转】
    计算机网络【一】:概述 【转】
    装饰模式-Decorator
    Java中的文件上传和下载
    模板方法模式-TemplateMethod
    策略模式-Strategy
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10348641.html
Copyright © 2020-2023  润新知