离散对数的求解(bsgs)

 

bsgs算法

主要用来解决${A^x} = B(\bmod C)$(c是质数),都是整数,已知A、B、C求x。

例:poj 2417 Discrete Logging

具体步骤如下:

先把$x = i*m - j$,其中$m = ceil(\sqrt C )$,(ceil是向上取整)。

这样原式就变为${A^{(i*m - j)}} = B(\bmod C)$,

再变为${A^j}*B = {A^{(m*i)}}(\bmod C)$。

枚举j(范围0-m),将${A^j}*B$存入hash表

枚举i(范围1-m),从hash表中寻找第一个满足${A^j} * B = {A^{(m * i)}}(\bmod C)$。

此时$x = i*m - j$即为所求。

 

在网上看到的其他题解大多用的是$x = i*m + j$,也可以做,只是会牵扯的求逆元,所以比较麻烦。使$x=i*m-j$就可以轻松避免这个问题了。

那么肯定有人会有疑问为何只计算到$m = ceil(\sqrt C )$就可以确定答案呢?

$x = i*m - j$ 也就是x 的最大值不会超过p,那超过p的怎么办 ?

有一个公式  ${a^{k\bmod (p - 1)}} = {a^k}(\bmod p)$    这个公式的推导需要用到费马小定理

$k\bmod p - 1$可以看做 $k - m*(p - 1)$ ,原式可化成  ${a^k}/{({a^{(p - 1)}})^m} = {a^k}(\bmod p)$ 

根据费马小定理 ${a^{(p - 1)}} = 1(\bmod p)$其中p为质数 ,a,p 互质,可得${a^k}/{1^m} = {a^k}(\bmod p){a^k} = {a^k}(\bmod p)$得证

 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<map>
 7 using namespace std;
 8 typedef long long ll;
 9 ll q=2147483647,a=3,yy,y2,m,ans,t;
10 map<ll,int>mp;
11 ll mod_pow(ll x,ll n,ll mod){
12     ll res=1;
13     while(n>0){
14         if(n&1)    res=res*x%mod; 
15         x=x*x%mod;
16         n>>=1;
17     }
18     return res;
19 }
20 
21 int main(){
22     while(~scanf("%lld%lld",&yy,&y2)){
23         mp.clear();
24         m=ceil(sqrt(q));
25         for(ll i=0;i<=m;i++){
26             if(i==0){
27                 ans=yy%q;
28                 mp[ans]=i;
29                 continue;
30             }
31             ans=ans*a%q;
32             mp[ans]=i;
33         }
34         bool flag=false;
35         ans=1;
36         t=mod_pow(a,m,q);
37         
38         
39         for(int i=1;i<=m;i++){
40             ans=ans*t%q;
41             if(mp[ans]){
42                 ll temp=i*m-mp[ans];
43                 ll rr=mod_pow(y2,temp,q);
44                 printf("%lld\n",rr);
45                 flag=true; 
46                 break;
47             }
48         }
49         if(!flag){
50         printf("No Solution\n"); 
51         }
52     }
53     return 0;
54 }

 

转载于:https://www.cnblogs.com/elpsycongroo/p/6719520.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值