同余

费马小定理

\(a^{p}\equiv a\ \ \ (mod\ p)\) 其中 \(p\) 为素数且 \(a\) 不是 \(p\) 的倍数.

证明:

引理: \(\binom{p}{n}\ mod\ p=\frac{p!}{n!(p-n)!}\ mod\ p=0\ \ \ \ (n\ne0或p)\) . 正确性显然

\[\begin{aligned} (b+1)^{p}&\equiv \binom{p}{p}b^{p}+\binom{p}{p-1}b^{p-1}+\binom{p}{p-2}b^{p-2}+···+\binom{p}{0}b^{0}\ \ \ \ mod\ p\\ &\equiv \binom{p}{p}b^{p}+\binom{p}{0}b^{0}\ \ \ \ mod\ p\\ &\equiv b^{p}+1\ \ \ \ mod\ p \end{aligned}\]

由上柿可知:

\[\begin{aligned} (b+1)^{p}&\equiv b^p+1\ \ \ mod\ p\\ &\equiv (b-1)^p+1\ \ \ mod\ p\\ &\equiv (b-2)^p+2\ \ \ mod\ p\\ &··\ ·\\ &\equiv (b-b)^p+b=b+1\ \ \ mod\ p\\ \end{aligned}\]

\(b=a-1\) 代入:

\[a^p\equiv a\ \ \ (mod\ p) \]

证毕.

应用1 : 显然 , \(a^{p-2}\equiv\frac{1}{a}\ \ \ mod\ p\) 在模数为素数, \(a,p\) 互质时,可用费马小定理求逆元。

应用2: 素性检验。

BSGS

求解: \(a^{t}\equiv n\ \ \ (mod\ p)\)

解:

根据欧拉定理有:

\[a^{\varphi (p)}\equiv1\ \ \ (mod\ p) \]

即:

\[a^{t}\equiv a^{t\ mod\ \varphi(p)}\ \ \ (mod\ p) \]

那么,若存在整数解 \(t\),则 \(t\in [0,\varphi (p)-1]\)

将区间 \([0,p]\) 分为 \(\sqrt p\) 段,每段长度为 \(k=\lfloor \sqrt p\ \rfloor+1\).

\(t=kx-y\ \ \ \ x\in[1,k]\ \ \ \ y\in[0,k-1]\),特判一下 \(t=0\) 的情况.

那么,有

\[a^{t}=a^{kx-y}\equiv b\ \ \ (mod\ p) \]

即,

\[a^{kx}\equiv ba^{y}\ \ \ (mod\ p) \]

对于 \(y\in[0,k-1]\),计算 \(ba^{y}\ mod\ p\),存到 \(hash\) 表里。

然后计算 \(x\in[1,k]\)\(a^{kx}\ mod\ p\) 判断\(hash\) 表里有没有这个值即可。

BSGS板子

#include<bits/stdc++.h>

#define LL long long 
using namespace std;

LL a,p,b;
int mod1=388211;
struct node
{
    int val,hah;//val存原始数据,hah存要存的值
};
vector<node>hash1[388311];

inline int qr()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}

inline LL poww(LL a,LL x)
{
    LL ans=1;
    a%=p;
    while(x)
    {
        if(x&1)
            ans=(ans*a)%p;
        a=(a*a)%p;
        x>>=1;
    }
    return ans%p;
}

inline void make_hash()//建hash表
{
    int k=sqrt(p)+1;
    for(register int i=0,j=b%p;i<k;i++)
    {
        node op=(node){j,i};//j是mod p之后的值,i表示 -y
        hash1[j%mod1].push_back(op);
        j=(LL)j*a%p;
    }
}

inline void clear_hash()//清空hash表
{
    int k=sqrt(p)+1;
    for(register int i=0,j=b%p;i<k;i++)
    {
        if(hash1[j%mod1].size())
            hash1[j%mod1].clear();
        j=(LL)j*a%p;
    }
}

inline LL BSGS(LL a,LL b,LL p)
{
    if(1%p==b%p)
        return 0;//特判 t=0
    int k=sqrt(p)+1;
    make_hash();
    int ak=poww(a,k);
    for(register int i=1,j=ak%p;i<=k;i++)//代入x
    {
        int siz=hash1[j%mod1].size();
        if(siz)//如果这个hash值存过
        {
            LL ans=0;
            for(register int c=0;c<siz;c++)//遍历这个hash值存的初始值
                if(j==hash1[j%mod1][c].val)//初始值相同
                    ans=(LL)i*k-hash1[j%mod1][c].hah;//更新答案,因为-y是从小到大存入hash表里的,所以后面的答案可能会更优
            if(ans)
                return ans;
        }
        j=(LL)j*ak%p;
    }
    return -1; //无解返回-1
}

int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    while(1)
    { 
        a=qr();
        p=qr();
        b=qr();
        if(!(a|b|p))
            return 0;
        LL res=BSGS(a,b,p);
        if(res==-1)
            printf("No Solution\n");
        else 
            printf("%lld\n",res);
        clear_hash();
    } 
    //system("pause");
    return 0;
}

扩展BSGS

求解: \(a^{t}\equiv n\ \ \ (mod\ p)\) \(a,p\) 不一定互质.

  • \(a^0\equiv b\ \ \ (mod\ p)\) , 则 \(t=0\) .
  • \(d=(a,p)\) ,

\(d=1\) 时就是常规 \(BSGS\).

\(d>1\) 时 , \(d\mid b\)时有解 , \(d\nmid b\)时无解.

将原式两边同时除以 \(d\) , 得到

\[\frac{a}{d}\ a^{t-1}\equiv\frac{b}{d}\ \ \ (mod\ \frac{p}{d}) \]

此时 \((\frac{a}{d},\frac{p}{d})=1\),故 \(\frac{a}{d}\) 的逆元一定存在,方程等价于:

\[a^{t-1}\equiv\frac{b}{d}\ (\frac{a}{d})^{-1}\ \ \ (mod\ \frac{p}{d}) \]

观察此时 \(a\)\(\frac{p}{d}\) 互质,直接用朴素版 \(BSGS\) 算法 , 反之再来一遍

EXBSGS板子

#include<bits/stdc++.h>
#define LL long long 
using namespace std;

int a,p,b;
int mod=388211;
struct node
{
    int val,hah;
};
vector<node>hash1[388211];

inline int qr()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}

int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1;y=0;
        return a;
    }
    int d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

inline int poww(int a,int x,int p)
{
    int ans=1;
    a%=p;
    while(x)
    {
        if(x&1)
            ans=(LL)ans*a%p;
        a=(LL)a*a%p;
        x>>=1;
    }
    return ans;
}

inline void make_hash(int a,int b,int p)//建立hash表
{
    int k=sqrt(p)+1;
    for(register int i=0,j=b%p;i<k;i++)
    {
        hash1[j%mod].push_back((node){j,i});
        j=(LL)j*a%p;
    }
}

inline void clear_hash(int a,int b,int p)//清空hash表
{
    int k=sqrt(p)+1;
    for(register int i=0,j=b%p;i<k;i++)
    {
        if(hash1[j%mod].size())
            hash1[j%mod].clear();
        j=(LL)j*a%p;
    }
}

inline LL BSGS(int a,int b,int p)
{
    make_hash(a,b,p);
    int k=sqrt(p)+1;
    int ak=poww(a,k,p);
    for(register int i=1,j=ak;i<=k;i++)
    {
        int siz=hash1[j%mod].size();
        if(siz)
        {
            int ans=0;
            for(register int c=0;c<siz;c++)
                if(j==hash1[j%mod][c].val)
                    ans=(LL)i*k-hash1[j%mod][c].hah;
            if(ans)
            {
                clear_hash(a,b,p);
                return ans;
            }
        }
        j=(LL)j*ak%p;
    }
    clear_hash(a,b,p);//清空hash表
    return -1;
}

int EXBSGS(int a,int b,int p)
{
    b=(b%p+p)%p;
    if(1%p==b%p)//特判t==0
        return 0;
    int x=0,y=0;
    int d=exgcd(a,p,x,y);//求a,p最大公因子
    if(d>1)
    {
        if(b%d)//b无法整除d无解
            return -1;
        exgcd(a/d,p/d,x,y);//求a/d逆元
        return EXBSGS(a,(LL)b/d*x%(p/d),p/d)+1;
    }
    return BSGS(a,b,p);
}

int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    while(1)
    {
        a=qr();
        p=qr();
        b=qr();
        if(!(a|p|b))
            return 0;
        LL res=EXBSGS(a,b,p);
        if(res==-1)
            printf("No Solution\n");
        else
            printf("%lld\n",res);
    }
    //system("pause");
    return 0;
}
posted @ 2021-02-12 00:23  江北南风  阅读(121)  评论(0编辑  收藏  举报