• 【模板】exBSGS/Spoj3105 Mod


    【模板】exBSGS/Spoj3105 Mod

    题目描述

    已知数(a,p,b),求满足(a^xequiv b pmod p)的最小自然数(x)

    输入输出格式

    输入格式:

    每个测试文件中最多包含(100)组测试数据。

    每组数据中,每行包含(3)个正整数(a,p,b)

    (a=p=b=0)时,表示测试数据读入完全。

    输出格式:

    对于每组数据,输出一行。

    如果无解,输出No Solution(不含引号),否则输出最小自然数解。


    BSGS

    (A perp p),那么({A^x,xle varphi(p)})遍历的剩余系({A^{kx},xle varphi(p)})一定也遍历,于是考虑枚举答案

    [A^xequiv B pmod p ]

    采用分块的思想,设(t=sqrt p,x=kt-b),式子就变成了

    [A^{kt-b}equiv B pmod p ]

    [A^{kt}equiv A^bBpmod p ]

    我们枚举(x=0 sim t),然后把得到的(A^xB)插到( t{Hash})表中去。

    然后枚举((A^t)^k)(k),查询( t{Hash})表中有没有(A^{kt})

    exBSGS

    如果(p)不是质数,存在无解的判定((gcd(A,p) mid B))(B ot=1)((B=1)特判(x=0))

    然后考虑操作一波式子

    [A^xequiv B pmod p,d=gcd(A,p) ]

    (d)除掉

    [A^{x-1}frac{A}{d}equiv frac{B}{d}pmod {frac{p}{d}} ]

    (C=frac{A}{d},B'=frac{B}{d},p'=frac{p}{d})

    原方程变为

    [CAequiv B' pmod {p'} ]

    然后重复是否无解的判断并向下递归,直到(Aperp p)或者无解

    然后(BSGS)即可,而常数(C)并不影响我们进行(BSGS)

    复杂度?显然递归的深度是(log)的,带上BSGS的就可以了。

    Code:

    #include <cstdio>
    #include <cmath>
    #include <unordered_map>
    std::unordered_map <int,int> Hash;
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    #define mul(a,b,p) (1ll*(a)*(b)%p)
    int exbsgs(int A,int B,int p)
    {
        if(B==1) return 0;
        int ct=0,d,k=1;
        while((d=gcd(A,p))^1)
        {
            if(B%d) return -1;
            B/=d,p/=d,++ct;
            k=mul(k,A/d,p);
            if(k==B) return ct;
        }
        int t=sqrt(p)+1,kt=1;
        Hash.clear();
        for(int i=0;i<t;i++)
        {
            Hash[mul(kt,B,p)]=i;
            kt=mul(kt,A,p);
        }
        k=mul(k,kt,p);
        for(int i=1;i<=t;i++)
        {
            if(Hash.find(k)!=Hash.end()) return i*t-Hash[k]+ct;
            k=mul(k,kt,p);
        }
        return -1;
    }
    int main()
    {
        int a,p,b;
        scanf("%d%d%d",&a,&p,&b);
        while(a&&p&&b)
        {
            int ans=exbsgs(a,b,p);
            if(~ans) printf("%d
    ",ans);
            else puts("No Solution");
            scanf("%d%d%d",&a,&p,&b);
        }
        return 0;
    }
    

    2018.12.19

  • 相关阅读:
    POJ2155 Matrix 【二维线段树】
    BZOJ4785 [Zjoi2017]树状数组 【二维线段树 + 标记永久化】
    B1027 打印沙漏
    Tomcat无法成功启动——双击startup.bat闪退
    MySQL在cmd命令行查看端口号
    1009 说反话(类似回文字符串)
    除基取余法,
    日期差值
    怎么把VS里的scanf_s换成scanf
    联想小新潮怎么修改fn热键以及怎么进入bios状态
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10143327.html
Copyright © 2020-2023  润新知