POJ---2417:Discrete Logging【BSGS算法】

题意:

a^x\equiv n~(mod~p)

p为素数且a,p互质,求最小的 x 满足上述同余方程

分析:

BSGS算法:

p为素数且a,p互质,有费马小定理a^{p-1}\equiv 1~(mod~p)而 a^0\equiv 1~(mod~p),所以在模p下有长度为P-1的循环节

若原方程有解,则最小的 x 必然在【0,p -1】内

m=\left \lceil\sqrt{p} \right \rceilx=i*m-ji\in [1,m]j\in [0,m-1],则:

a^{i*m-j}\equiv n~(mod~p)

a^{i*m}\equiv n*a^j~(mod~p)

i,j的范围很小,于是枚举j,将 n*a^j 存入hash表,hash[n*a^j ] = j,

枚举 i ,若a^i*m 的值在hash表中存在,则找到 x 的最小值为 i*m - j

不难看出,i*m-j 能表示所有在【0,p-1】内的数,如果枚举完 都还没有找到,则无解

在用map标记时,j = 0无法标记,通常将 j 枚举到mi枚举到m+1

代码:

#include <map>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int a,p,c;
ll qpow(ll a,ll x)
{
    ll res = 1;
    while(x){
        if(x&1) res = res * a % p;
        a = a * a % p;
        x >>= 1;
    }
    return res%p;
}
int BsGs()
{
    map<ll,int> mp;
    int k = sqrt(p*1.0) + 0.5;
    ll v = c;
    for(int j = 1; j <= k ; ++j){
       v =  v * a % p;
       mp[v] = j;
    }
    v = qpow(a,k);
    ll vv = 1;
    for(int i = 1; i <= k; ++i){
         vv = vv * v % p;
         if(mp[vv]) return i * k - mp[vv];
    }
    return -1;
}
int main()
{
    while(cin>>p>>a>>c)
    {
        int ans = BsGs();
        if(ans == -1) cout<<"no solution"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值