• BSGS入门


    做了这么长时间数论 应该整合一下

    在mod意义下 我们能完成的运算:

    减(mod m + m mod m) 

    快速幂 快速乘

    逆元(除) 有有解的条件

    开方? 这个设计原根的知识 下一篇讲

    然后 就是取对数了 也就是著名的 离散对数 问题

    (话说连续对数还不太熟练呢.....)

    Question:  给定方程  a ^ x ≡ b (mod c) 求x

    Solution:

    首先可以容斥地发现 如果有解 0~c范围内一定有一个解

    所以枚举! O(c)即可通过本题!

    End.

    (啪!)

    大部分情况下模数都是1e9+7这样的东西 所以枚举显然是过不去的

    由于连续情况下 我们并不能高效的得出某一个对数的具体值

    所以枚举的思路依然要保留

    我们发现其实上面的算法有一个很小的思路优化 :  枚举0~c-1的每个数

    也就是说 这里面的每个数 都代表了一类数

    (虽然并不是剩余系)

    所以我们考虑 能不能先算出一部分答案 然后利用这些答案去简化别的答案的运算

    于是! Baby-step giant-step 思想就诞生了

    Baby_step,giant_step,意为先小步,后大步,这是一个很神奇的想法。

    能够降低枚举的规模从 n 到 sqrt(n),怎么实现的呢,我们看下面。

    sqrt(n) -> 考虑分块 (记块大小为B)

    然后我们发现 每个块的大小恒定 所以可以拆分成i=x*B+y的形式

    我们先O(sqrt(n)) 处理0~B-1的答案 

    如果没有找到就存HASH表里

    然后O(sqrt(n)) 遍历所有块同时O(1)查找有没有答案

    然后就OK

    但是有一个问题

    这里必须保证把a^i除到b那边以后没有问题

    也就是a 有 mod c 的逆元 

    所以我们可以一直求gcd(a,c) 然后除掉并且每次拿一个a出来(++tot)

    最后答案加上tot就OK

    Code:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<algorithm>
      5 #define ms(a,b) memset(a,b,sizeof a)
      6 #define inf 2147483647
      7 #define itn int
      8 #define rep(i,a,n) for(itn i = a;i <= n;i++)
      9 #define per(i,n,a) for(itn i = n;i >= a;i--)
     10 #define eps 1e-8
     11 using namespace std;
     12 typedef long long ll;
     13 const int N = 50005;
     14 //head
     15 int X,Z,K;
     16 ll gcd(ll a,ll b){return b ? gcd(b,a%b) : a;}
     17 ll exgcd(ll a,ll b,ll &x,ll &y) {
     18     if(!b) {
     19     x = 1,y = 0;
     20     return a;
     21     }
     22     ll t = exgcd(b,a%b,y,x);
     23     y -= (a/b) * x;
     24     return t;
     25 }
     26 
     27 ll inv(ll a,ll p) {
     28     ll x,y;
     29     exgcd(a,p,x,y);
     30     return (x%p+p)%p;
     31 }
     32 
     33 struct Hash {
     34     const static int H = 999979;
     35     int head[H],nxt[N],num[N],val[N],cnt;
     36     void init() {
     37     cnt = 0;
     38     ms(head,0),ms(nxt,0),ms(val,0);
     39     }
     40     void ins(int x,int y) {
     41     int h = x % H;
     42     for(int i = head[h];i;i = nxt[i]) {
     43         if(num[i] == x) {val[i] = y;return;}
     44     }
     45     nxt[++cnt] = head[h];
     46     head[h] = cnt;
     47     num[cnt] = x,val[cnt] = y;
     48     }
     49     int qry(int x) {
     50     int h = x % H;
     51     for(int i = head[h];i;i = nxt[i]) {
     52         if(num[i] == x) return val[i];
     53     }
     54     return -1;
     55     }
     56 }HASH;
     57 
     58 //a ^ x == b(mod p)
     59 int BSGS(int a,int b,int p) {
     60 // gcd(a,p) <- 1
     61     int tot = 0,G;
     62     int d = 1;
     63     while( (G = gcd(a,p)) ^ 1 ) {
     64     if(b%G) return -1;
     65     tot++;
     66     b /= G,p /= G;
     67     d = (ll)d * (a/G) % p;
     68     }
     69     b = (ll)b * inv(d,p) % p;
     70 
     71 // ins(a^(0~B-1))
     72     HASH.init();
     73     int B = sqrt(p);
     74     int x = 1;
     75     rep(i,0,B-1) {
     76     if(x == b) return i + tot;
     77     HASH.ins((ll)x * b % p,i);
     78     x = (ll)x * a % p;
     79     }
     80 
     81 //a^im = b * a^(-y)
     82 //O(B) + O(hash)
     83     int q = x;
     84     for(int i = B;i - (B-1) <= p-1;i += B) {
     85     int tmp = HASH.qry(q);
     86     if(tmp != -1) return i - tmp + tot;
     87     q = (ll)q * x % p;
     88     }
     89     return -1;
     90 }
     91 
     92 bool spj() {
     93     if(X == 0) {
     94     puts("No Solution");
     95     return 1;
     96     }
     97     int res = 1;
     98     rep(i,0,10) {
     99     if(res == K) {
    100         printf("%d
    ",i);
    101         return 1;
    102     }
    103     res = (ll)res * X % Z;
    104     }
    105     return 0;
    106 }
    107 
    108 //x ^ y == k(mod z)
    109 main() {
    110     while(~scanf("%d%d%d",&X,&Z,&K)) {
    111     if(!X && !Z && !K) return 0;
    112     X %= Z;K %= Z;
    113     if(spj()) continue;
    114     int ans = BSGS(X,K,Z);
    115     if(ans == -1) puts("No Solution");
    116     else printf("%d
    ",ans);
    117     }
    118 }
    View Code
    > 别忘了 总有人在等着你
  • 相关阅读:
    根据svm将视频帧转换为img
    Mp4 to Img
    Python_02 基本数据类型、while循环
    Python_01 执行方式、解释器路径、编码、变量、条件语句
    数字货币,新时代货币革命的起点?
    企业区块链项目中需要避免的常见错误
    2021 年五大物联网 (IoT) 趋势
    揭开AI、机器学习和深度学习的神秘面纱
    物联网的安全性与法规的未来
    为什么分布式云是下一代云计算?Gartner分析师这样解释
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9803091.html
Copyright © 2020-2023  润新知