zoukankan      html  css  js  c++  java
  • P4195 【模板】exBSGS/Spoj3105 Mod

    传送门

    首先要懂得 $BSGS$,$BSGS$ 可以求出关于 $Y$ 的方程 $X^Y equiv Z (mod mo)$ 的最小解,其中 $gcd(X,Z)=1$

    $exBSGS$ 算是 $BSGS$ 的进一步扩展,使得当 $gcd(X,Z)!=1$ 时仍然适用

    先把方程转换成 $X^Y+k*mo=Z$ 的形式

    因为 $Y,k$ 都是整数,所以 $Z$ 必须是 $gcd(X,mo)$ 的倍数,不然无解

    所以可以把方程左右同除 $gcd(X,mo)$,变成 $X^{(Y-1)}*frac{X}{gcd(X,mo)}+k*frac{mo}{gcd(X,mo)}=frac{Z}{gcd(X,mo)}$

    其实这个方程就相当于 $frac{X}{gcd(X,mo)}*X^{(Y-1)} equiv frac{Z}{gcd(X,mo)} (mod frac{mo}{gcd(X,mo)})$

    发现 $frac{X}{gcd(X,mo)}$ 只是一个系数,如果此时 $gcd(X,frac{mo}{gcd(X,mo)})=1$ 则可以直接套用 $BSGS$ 求解

    如果此时 $gcd(X,frac{mo}{gcd(X,mo)})!=1$ 则可以继续上述操作直到 $gcd$ 为 $1$

    设第 $i$ 次操作的 $gcd$ 为 $d_i$,总共进行了 $T$ 次操作

    则最后式子的形式为 $frac{X^T}{prod _{i=1}^{T}d_i}X^{Y-T} equiv frac{Z}{prod _{i=1}^{T}d_i} (mod frac{mo}{prod _{i=1}^{T}d_i})$

    要记得特判 $Y in [0,T]$ 的情况

    具体看代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double ldb;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    int gcd(int a,int b) { return b ? gcd(b,a%b) : a; }
    map <int,int> mp;
    inline int ksm(int x,int y,int mo)
    {
        int res=1;
        while(y)
        {
            if(y&1) res=1ll*res*x%mo;
            x=1ll*x*x%mo; y>>=1;
        }
        return res;
    }
    // X^Y=Z (mod mo)
    void exBSGS(int X,int Z,int mo)
    {
        if(Z==1) { printf("0
    "); return; }
        int d=gcd(X,mo),t=0,k=1;
        while(d!=1)
        {
            if(Z%d) { printf("No Solution
    "); return; }
            t++; k=(1ll*k*(X/d))%mo; mo/=d; Z/=d;
            if(k==Z) { printf("%d
    ",t); return; }
            d=gcd(X,mo);
        }
        int m=sqrt(mo)+1; mp.clear();
        for(int b=0,s=Z; b<m; b++,s=1ll*s*X%mo) mp[s]=b;
        for(int a=1,p=ksm(X,m,mo),s=1ll*k*p%mo; a<=m+1; a++,s=1ll*s*p%mo)
        {
            if(mp.find(s)==mp.end()) continue;
            printf("%d
    ",a*m-mp[s]+t); return;
        }
        printf("No Solution
    ");
    }
    int main()
    {
        int X=read(),mo=read(),Z=read();
        while(X||Z||mo)
        {
            exBSGS(X,Z,mo);
            X=read(),mo=read(),Z=read();
        }
        return 0;
    }
  • 相关阅读:
    win10下的MyEclipse2017 ci7 破解教程+全套资源+失败处理(转)
    layui layer.open() 弹层开启后 Enter回车 遮罩层无限弹处理
    layui 或者layer 父页面获取子页面数据 或者子页面获取父页面操作方法(转)
    layui弹出层两个以上置顶弹出
    div自动获焦并将光标定位到最后
    hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别
    形参与实参的区别
    linux下安装Mysql(干货!!!)解决mysql 1130问题,远程登录问题
    linux下安装Mysql(干货!!!)
    java文件上传与下载
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11278960.html
Copyright © 2011-2022 走看看