• bsgs算法详解


    例题  poj 2417bsgs  http://poj.org/problem?id=2417

    这是一道bsgs题目,用bsgs算法,又称大小步(baby step giant step)算法,或者拔(b)山(s)盖(g)世(s)算法,或者北(b)上(s)广(g)深(s)算法。。。

    题目大意就是

    给定a,b,p,求最小的非负整数x,满足  ax ≡ b(mod p)

    先令 x = i*m-j,其中 m=ceil(sqrt(p)),ceil是向上取整。

    这样原式就变为     ai*m-j = b (mod p),

    移项就变成了        ai*m = b*aj (mod p)

    枚举j (范围0-m) ,将 b*aj  存入hash表。

    枚举i (范围1-m) ,从hash表中寻找第一个满足ai*m = b*aj  (mod p)。

    此时   x = i*m-j  就是所要求的。

    那么为什么只计算到 m=ceil(sqrt(q))  就可以确定答案呢?

    因为 x = i*m-j , 所以x 的最大值不会超过p

    a(k mod p-1) = ak (mod p)  证明这个公式,(需要用到费马小定理)

    k mod p-1 就是 k-m(p-1) ,原式就变成了 ak-m(p-1) ≡ ak (mod p)

    再变一步  a/ am(p-1) ≡ ak (mod p)

    这时让 am(p-1) ≡ 1 (mod p) 就行了。

    由费马小定理知: 当p为质数且 (a,p时 ap-1 ≡ (mod p)

    所以推出 为质数 且 (a,p)=1 这个条件, 所以 a(k mod p-1) ≡ (mod p) 

    所以:如果枚举 的话枚举到 p 即可。

    所以使 imj<=p , 即 m=⌈√p⌉ , i,最大值也为m。

     

     这是代码,结合上面的看

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<map>
     4 #include<cmath>
     5 
     6 using namespace std;
     7 typedef long long ll;
     8 
     9 map<ll,int>mp;
    10 ll p,a,b;
    11 ll n,m,now,ans,t;
    12 bool flag;
    13 
    14 ll fast_pow(ll x)
    15 {
    16     ll sum = 1;
    17     ll aa = a;
    18     while (x>0)
    19     {
    20         if (x&1) 
    21             sum = (sum*aa)%p;
    22         x = x>>1;
    23         aa = (aa*aa)%p;
    24     }
    25     return sum;
    26 }
    27 int main()
    28 {
    29     while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
    30     {
    31         if(a%p==0)
    32         {
    33             printf("no solution
    ");
    34             continue;
    35         }
    36         mp.clear();
    37         m = ceil(sqrt(p));
    38         flag = false ;
    39         now = b%p;        //b*a^j 当j==0时 
    40         mp[now] = 0;
    41         for(int i=1;i<=m;++i)
    42         {
    43             now = (now*a)%p;
    44             mp[now] = i;
    45         }
    46         t = fast_pow(m);
    47         now = 1;
    48         for(int i=1;i<=m;++i)    //枚举 (a^m)^i
    49         {
    50             now = (now*t)%p;
    51             if(mp[now])
    52             {
    53                 flag = true;
    54                 ans = i*m-mp[now];
    55                 printf("%lld
    ",(ans%p+p)%p);    //printf("%lld
    ",(ans%p+p)%p);
    56                 break;
    57             }
    58         }
    59         if(!flag) printf("no solution
    ");
    60     }
    61     return 0;
    62 }
    bsgs
  • 相关阅读:
    图片懒加载
    文字表情转换成小图标
    页面跳页面的参数获取
    vue v-for里面再套v-if和v-esle
    滚动条样式的修改
    vue-cil生产环境和发布环境的配置
    css隐藏滚动条并且可以滑动
    vue-cli脚手架一些插件安装elementui和axios
    闭包
    定时器、运动、日历
  • 原文地址:https://www.cnblogs.com/mjtcn/p/6879074.html
Copyright © 2020-2023  润新知