一.引入:

若存在一个式子a^b ≡ c (mod p) (p ≡ 1000000007,且0<a,b,c<p)

   已知a,b,求c.

     这不就是快速幂嘛!

  已知a,c,求b.

    这就是我们需要研究的问题!用到了BSGS!

题目链接:poj 2417 bsgs

二.概念

BSGS:

又名大步小步算法.具体的我也不清楚啦~

那么发明来做什么事情呢?

如上所述:

  就是用来求解a^x ≡ b (mod p)这样的式子

    PS:已知a,b,p

        求最小x

三.做法

首先,我们将x用i*m-j来表示,其中我们的m=seil(sqrt(p)),(seil为向上取整)

然后我们用i*m-j代替掉x,所以原式就变成了这个样子

        a^(i * m-j) ≡ b (mod p)

又因为a^(i * m-j)  =>  a^(i * m)/a^j

所以原式又变了模样:

        a^(i * m)/a^j ≡ b (mod p)

又因为在"≡"(同余号)的两侧同时乘以一个相同的数依旧是成立的,如果不明白可以手动模拟一下,

给出个栗子~

  3 ≡ 10 (mod 7),当两边同乘以5时式子变成: 15 ≡ 50 (mod 7)

  因为15%7==1&&50%7==1,所以原式依旧成立

所以将式子两边同时乘以a^j

那么式子就又发生了改变:

        a^(i * m) ≡ b * a^j (mod p)

    = (a^m)^i ≡ b * a^j (mod p)

所以问题就简单多了!

因为a^m是常数,b是常数,p也是常数,所以只有 i 跟 j 是未知的,暴力枚举!

但是有一点是我们不能够忘记的:

m的取值范围:1 —— p(p是当b==0时),所以

首先将 j 从1 到 p-1 进行枚举一遍,求出b * a^j 的值丢到hash(大佬是用map做的)里面咯(讲真hash不会用...怪我咯?)

  思路是这样的:(其实就是hash啦~)

        (b*a^j)%p(如果p太小换成另外一个比较大的质数)作为下标,里面存着当前计算出来的数,以及当前的 j (可以用vector~)

然后,枚举 j ,我们大可以设a^m==c

将 i 从 1 到p-1枚举一遍,如果求出的数在hash里面找到了,则说明当前的数就是 i (能够成立的) 最小值,跳出循环,用当前的i,以及记录下来的 j 计算对应的 i 求出 x

则x就是最小的解

C++代码实现:

(map方法:)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<map>
  6. #include<cmath>
  7.  
  8. using namespace std;
  9. typedef long long LL;
  10.  
  11. LL a,b,c;
  12. map<LL,LL> mp;
  13.  
  14. LL qsm(LL m)
  15. {
  16. LL n = a;
  17.  
  18. if(m == ) return ;
  19.  
  20. LL t = qsm(m/);
  21.  
  22. t = 1LL*t*t%c;
  23. if(m&) t = 1LL*t*n%c;
  24.  
  25. return t;
  26. }
  27.  
  28. int main()
  29. {
  30. //a^im=b*a^j(mod c)
  31. while (scanf("%lld%lld%lld",&c,&a,&b)!=EOF)
  32. {
  33. mp.clear(); //清空
  34. if (a%c==) //判断a,c 是否互质,因为c 是质数,所以直接判断是否整除即可
  35. {
  36. printf("no solution\n");
  37. continue;
  38. }
  39. LL m=ceil(sqrt(c));
  40. LL ans;
  41. for (LL j=; j<=m; j++)
  42. {
  43. if (j==)
  44. {
  45. //当j=0时,a^j=1, b*a^j=b
  46. ans=b%c;
  47. mp[ans]=j;
  48. continue;
  49. }
  50. ans=(ans*a)%c;
  51. //括号里的ans指a^(j-1)*b,(a^(j-1)*b)*a=(a^j)*b
  52. mp[ans]=j;//在((a^j)*b)%c的位置记录下j
  53. }
  54. LL t=qsm(m);//t=a^m
  55. ans=;
  56. bool p=false;
  57. for (LL i=; i<=m; i++)
  58. {
  59. ans=(ans*t)%c;//括号里的ans指的是((a^m)^(i-1))*(a^m)=(a^m)^i=a^(im)
  60. if (mp[ans])
  61. {
  62. LL t=i*m-mp[ans];//t=x,因为我们设的x=i*m-j
  63. printf("%lld\n",t);
  64. p=true;
  65. break;
  66. }
  67. }
  68. if (!p)
  69. printf("no solution\n");
  70. }
  71. }

End.

BSGS ! x的更多相关文章

  1. 【POJ 3243】Clever Y 拓展BSGS

    调了一周,我真制杖,,, 各种初始化没有设为1,,,我当时到底在想什么??? 拓展BSGS,这是zky学长讲课的课件截屏: 是不是简单易懂.PS:聪哥说“拓展BSGS是偏题,省选不会考,信我没错”,那 ...

  2. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  3. 【BZOJ-3122】随机数生成器 BSGS

    3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1362  Solved: 531[Submit][Sta ...

  4. BSGS[bzoj2242][bzoj3122]

    数论题. 操作一:直接快速幂就好了. 操作二:我用了exgcd,shy和lyz都喜欢欧拉函数...QAQ最后这块还写错了. 对于ax+by=gcd(a,b)的形式,我们可以把他们变成y'x+p'y=1 ...

  5. 【BZOJ2242】【SDoi2011】计算器 快速幂+EXGCD+BSGS

    Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...

  6. BZOJ-2242 计算器 快速幂+拓展欧几里得+BSGS(数论三合一)

    污污污污 2242: [SDOI2011]计算器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 2312 Solved: 917 [Submit][S ...

  7. bzoj 1467: Pku3243 clever Y 扩展BSGS

    1467: Pku3243 clever Y Time Limit: 4 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description 小 ...

  8. BSGS模版 a^x=b ( mod c)

    kuangbin的BSGS: c为素数: #define MOD 76543 int hs[MOD],head[MOD],next[MOD],id[MOD],top; void insert(int ...

  9. bzoj 2242: [SDOI2011]计算器 BSGS+快速幂+扩展欧几里德

    2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 你被 ...

  10. 【poj3358】消因子+BSGS 或 消因子+欧拉定理 两种方法

    题意:给你一个分数,求它在二进制下的循环节的长度,还有第一个循环节从哪一位开始. For example, x = 1/10 = 0.0001100110011(00110011)w and 0001 ...

随机推荐

  1. 【C#】上机实验一

    1.开发一个控制台应用程序,根据提示从键盘获取一个华氏温度,请转换并输出对应的摄氏温度. using System; namespace Project { class Program { publi ...

  2. 使用QFileInfo类获取文件信息(文件的所有权和权限检查在默认情况下是被禁用的。要使能这个功能 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;)

    QFileInfo类为我们提供了系统无关的文件信息,包括文件的名字和在文件系统中位置,文件的访问权限,是否是目录或符合链接,等等.并且,通过这个类,可以修改文件的大小和最后修改.读取时间.同时,QFi ...

  3. 14-MySQL DBA笔记-运维技巧和常见问题处理

    第14章 运维技巧和常见问题处理 DBA的成长,离不开对各种问题的处理.本章将为读者介绍一些运维技巧和常见问题的处理方法.我们需要意识到,别人的经验代替不了自己的经验,所以,多实践.多处理问题,最终会 ...

  4. (九)Hibernate 的复合主键

    一.什么是复合主键? 一张表的主键是由多个字段组成,这个主键就被称为复合主键.  主键是唯一确定某条记录的字段,比如公民的身份证号就是一个主键,因为由身份证号这个主键就可以确定 某个公民.   有一种 ...

  5. Spring 后台方法 重定向 与 转发

    一.重定向:重定向是客户端行为,在使用时,务必使用全路径,否则可能因为外部环境导致错误 1.URL改变为重定向的URL地址 2.前台页面不能使用Ajax请求提交, 应该使用form表单提交 方法一.参 ...

  6. Opencl 学习笔记

    1. HelloWorld

  7. opencv 加载pb

    1.错误1         Tensor's data type is not supported the type of Mul  is DF_Float 2.  错误2 type == " ...

  8. springboot学习链接

    https://github.com/wuyouzhuguli/SpringAll

  9. pymysql 1064, 'You have an error in your SQL syntax; check the manual that corresponds to

    在python 连接mysql时,最近一直出现了 1064, 'You have an error in your SQL syntax; check the manual that correspo ...

  10. Dell T30解决报Alert! Cover was previously removed.

    DELL T30自检中卡在F1/F2/F5选项,需要F1手动启动时报:Alert! Cover was previously removed是指向机器盖问题 [解决方法]: 1.检查机箱盖是否有盖紧 ...