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\n",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\n",ans);
117     }
118 }

原文地址:https://www.cnblogs.com/yuyanjiaB/p/9803091.html

时间: 2024-11-09 16:55:10

BSGS入门的相关文章

数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho

数论入门2 另一种类型的数论... GCD,LCM 定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有: 将a和b分解质因数为\(a=p1^{a1}p2^{a2}p3^{a3}...pn^{an},b=p1^{b1}p2^{b2}p3^{b3}...pn^{bn}\),那么\(gcd(a,b)=\prod_{i=1}^{n}pi^{min(ai,bi)},lcm(a,b)=\prod_{i=1}^{n}pi^{max(ai,bi)}\)(0和任何

R语言快速上手入门

R语言快速上手入门 课程学习网址:http://www.xuetuwuyou.com/course/196 课程出自学途无忧网:http://www.xuetuwuyou.com 课程简介 本教程深入浅出地讲解如何使用R语言玩转数据.课程中涵盖R语言编程的方方面面,内容涉及R对象的类型.R的记号体系和环境系统.自定义函数.if else语句.for循环.S3类R的包系统以及调试工具等.本课程还通过示例演示如何进行向量化编程,从而对代码进行提速并尽可能地发挥R的潜能.本课程适合立志成为数据科学家的

笔记:Spring Cloud Zuul 快速入门

Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了所有其他微服务的实例信息,这样的设计非常巧妙的将服务治理体系中维护的实例信息利用起来,使得维护服务实例的工作交给了服务治理框架自动完成,而对路由规则的维护,默认会将通过以服务名作为 ContextPath 的方式来创建路由映射,也可以做一些特别的配置,对于签名校验.登录校验等在微服务架构中的冗余问题

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024

JAVA通信系列二:mina入门总结

一.学习资料 Mina入门实例(一) http://www.cnblogs.com/juepei/p/3939119.html Mina入门教程(二)----Spring4 集成Mina http://www.cnblogs.com/juepei/p/3940396.html Apache Mina 入门实例--创建一个MINA时间服务http://loftor.com/archives/apache-mina-quick-start-guide.html MINA2.0用户手册中文版--系列文

Storm入门(四)WordCount示例

Storm API文档网址如下: http://storm.apache.org/releases/current/javadocs/index.html 一.关联代码 使用maven,代码如下. pom.xml  和Storm入门(三)HelloWorld示例相同 RandomSentenceSpout.java /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor lice

浅谈Ubuntu PowerShell——小白入门教程

早在去年八月份PowerShell就开始开源跨平台了,但是一直没有去尝试,叫做PowerShell Core. 这里打算简单介绍一下如何安装和简单使用,为还不知道PowerShell Core on Ubuntu的同学们提供一点小小的入门帮助,谢谢大家支持~ PowerShell Core是由Microsoft开发的运行在.Net Core上的开源跨平台的任务自动化和配置管理系统. 1.   在Ubuntu 16.04上安装PowerShell Core a)         导入公共存储库GP

2.vue.js 入门环境搭建

原文链接:http://blog.csdn.net/luckylqh/article/details/52863026?locationNum=2&fps=1 vue这个新的工具,确实能够提高效率,在经历的一段时间的摧残之后,终于能够有一个系统的认识了,下面就今天的收获做一个总结,也是vue入门的精髓: 1.要使用vue来开发前端框架,首先要有环境,这个环境要借助于node,所以要先安装node,借助于node里面的npm来安装需要的依赖等等. 这里有一个小技巧:如果在cmd中直接使用npm来安

学习mysql的笔记:mysql十大基本入门语句

学习mysql数据库,从最简单的十条入门语句开始.刚开始学习mysql,老师让我们用cmd控制台输入语句,而不是选择用工具输入,这是为了我们能够先熟悉mysql语句. 首先要先进入mysql,语句为:mysql -hlocalhost -uroot -p  然后回车,输入密码. C:\Users\Administrator>mysql -hlocalhost -uroot -p Enter password: ****** 成功进入的话会出现 Welcome to the MySQL monit