高次同余方程:

一、算法进阶给的板子:

int bsgs(int a,int b,int p)
{
    map<int,int>_hash;
    _hash.clear();
    b%=p;
    
    int t=(int) sqrt(p)+1;
    for(int j=0;j<t;j++)
    {
        int val=(ll) b*power(a,j,p)%p;
        _hash[val]=j;
    }
    
    a=power(a,t,p);
    if(a==0) return b==0?1:-1;
    for(int i=0;i<=t;i++)
    {
        int val=power(a,i,p);
        int j=_hash.find(val)==_hash.end()?-1:_hash[val];
        if(j>=0&&i*t-j>=0) return i*t-j;
    }
    
    return -1;
}

二、
Discrete Logging POJ - 2417

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#define ll long long
using namespace std;
ll a,b,p;

ll mypow(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%p;
        a=(a*a)%p;
        b>>=1;
    }
    return ans%p;
}

ll bsgs(ll a,ll b,ll p)
{
    a%=p,b%=p;
    if(b==1) return 0;
    if(b==0&a==0) return 1;
    if(!a) return -1;
    map<ll,ll>_hash;
    map<ll,bool>ha;

    ll t=(ll) ceil(sqrt(p*1.0));

    for(ll j=0;j<t;j++)
    {
        ll val=(b*mypow(a,j,p))%p;

        {
            ha[val]=true;
            _hash[val]=j;
        }

    }
    a=mypow(a,t,p);

    for(int i=1;i<=t;i++)
    {
        ll val=mypow(a,i,p);
        ll j=-1;
        if(ha[val]) j=_hash[val];
        //cout<<"i:t:j:  "<<i<<t<<j<<endl;
        if(j>=0&&i*t-j>=0) return i*t-j;
    }
    return -1;

}

int main(void)
{
    while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
    {
        ll k=bsgs(a,b,p);
        if(k==-1)
        {
            printf("no solution\n");
        }
        else printf("%lld\n",k);
    }
    return 0;
}

算法进阶:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#define ll long long
using namespace std;
ll a,b,p;

ll mypow(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%p;
        a=(a*a)%p;
        b>>=1;
    }
    return ans%p;
}

ll bsgs(ll a,ll b,ll p)
{
    map<ll,ll>_hash;
    map<ll,bool>ha;
    _hash.clear();
    b%=p;
    ll t=(ll) sqrt(p+0.5);
    //cout<<"t:"<<t<<endl;
    for(ll j=0;j<t;j++)
    {
        ll val=(b*mypow(a,j,p))%p;
        if(!ha[val])
        {
            ha[val]=true;
            _hash[val]=j;
        }

    }
    a=mypow(a,t,p);
    if(a==0) return b==0?1:-1;

    for(int i=0;i<=t;i++)
    {
        ll val=mypow(a,i,p);
        ll j=-1;
        if(ha[val]) j=_hash[val];
        if(j>=0&&i*t-j>=0) return i*t-j;
    }
    return -1;

}

int main(void)
{
    while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
    {
        ll k=bsgs(a,b,p);
        if(k==-1)
        {
            printf("no solution\n");
        }
        else printf("%lld\n",k);
    }
    return 0;
}

三、洛谷
P4195 【模板】exBSGS/Spoj3105 Mod
一直T。。。可能得手写hash吧。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<unordered_map>
#define ll long long
using namespace std;
ll a,b,p;

ll gcd(ll a,ll b)
{
    if(b==0) return a;
    else return gcd(b,a%b);
}

void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1,y=0;
        return ;
    }
    exgcd(b,a%b,x,y);
    ll z=x;
    x=y;
    y=z-a/b*y;
    return ;
}

ll bsgs(ll a,ll b,ll p)
{
    a%=p,b%=p;
    if(b==1) return 0;
    if(b==0&&a==0) return 1;
    if(!a) return -1;
    if(!b)
    {
        int ret=0,d;
        while((d=gcd(a,p))!=1)
        {
            ret++;
            p/=d;
            if(p==1) return ret;
        }
        return -1;
    }

    ll k=0,temp=1,d;

    while(true)
    {
        d=gcd(a,p);
        if(d==1) break;

        if(b%d) return -1;
        b/=d;
        p/=d;
        temp=temp*(a/d)%p;
        k++;
        if(temp==b) return k;
    }
    ll x,y;
    exgcd(temp,p,x,y);
    x=(x%p+p)%p;
    b=b*x%p;
    //cout<<a<<"  "<<b<<"  "<<p<<endl;

    ll m=ceil(sqrt(p*1.0));
    ll e=1;
    b%=p;

    unordered_map<int,int>ha;
    ha[1]=0;
    for(int i=1;i<m;i++)
    {
        e=e*a%p;
        if(ha.find(e)==ha.end())
        {
            ha[e]=i;
        }
    }

    e=e*a%p;

    ll inv;
    exgcd(e,p,x,y);
    inv=(x%p+p)%p;

    for(int i=0;i<m;i++)
    {
        if(ha.find(b)!=ha.end())
        {
           return  i*m+ha[b]+k;
        }
        b=b*inv%p;

    }

   return -1;
}

int main(void)
{
    while(scanf("%lld%lld%lld",&a,&p,&b),a||b||p)
    {
        ll k=bsgs(a,b,p);
        if(k==-1) printf("No Solution\n");
        else printf("%lld\n",k);
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值