https://scut.online/p/485

给定a和n,求有多少个质数p,满足n是使得a^n=1 mod p成立的最小正整数。

翻译:求有多少个质数p,使得a模p的阶delta_m(a)是n

先验证 a^n=1 mod p 成立

那么假如还有更小的m使得 a^m=1 mod p 成立,则这个p不合要求

由阶的性质有delta_m(a)|n,故只需要检查n的所有因子就可以了。

但其实不需要检查所有因子,只需要检查n的所有质因子。(从板子上面可以看出来,但是为什么)

即 a^(p_i) = 1 mod p 是否成立,假如恒不成立,则n是a模p的阶,其中p_i是n的每种质因子。

证明如下:很显然的,原本我们要检查n的所有因子才能确定阶,但是有一个更好的办法。

假如还有更小的m使得 a^m=1 mod p 成立,那么m的倍数km也一定满足 a^(km)=1 mod p 成立,那么从n中只去除一个质因子p_i,假如这个t=(n/p_i)有 a^t=1 mod p ,则可能存在更小的m使得 a^m=1 mod p 成立。否则假如 a^t != 1 mod p ,则t的所有因子也都不需要检查了。

这样就只需要检查log次。

1e9都直接暴力,快速幂还有个logn,真的服了没话讲。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. int q, n;
  5. const int MAXN = 1e7 + 5;
  6. int p[MAXN], ptop;
  7. int minp[MAXN];
  8. bool np[MAXN];
  9. void sieve(int n) {
  10. np[1] = 1;
  11. for(int i = 2; i <= n; i++) {
  12. if(!np[i]) {
  13. p[++ptop] = i;
  14. minp[i] = i;
  15. }
  16. for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
  17. minp[t] = p[j];
  18. np[t] = 1;
  19. if(i % p[j] == 0)
  20. break;
  21. }
  22. }
  23. }
  24. int qpow(ll x, int n, int p) {
  25. ll res = 1;
  26. while(n) {
  27. if(n & 1)
  28. res = res * x % p;
  29. x = x * x % p;
  30. n >>= 1;
  31. }
  32. return res;
  33. }
  34. int ans[MAXN], atop;
  35. int fac[60], ftop;
  36. void GetFactor(int n) {
  37. ftop = 0;
  38. while(n != 1) {
  39. int cp = minp[n];
  40. fac[++ftop] = cp;
  41. while(n % cp == 0)
  42. n /= cp;
  43. }
  44. }
  45. int check(int n, int P) {
  46. if(qpow(q, n, P) != 1)
  47. return 0;
  48. for(int i = 1; i <= ftop; ++i) {
  49. int t = n / fac[i];
  50. if(qpow(q, t, P) == 1)
  51. return 0;
  52. }
  53. return 1;
  54. }
  55. int main() {
  56. #ifdef Yinku
  57. freopen("Yinku.in", "r", stdin);
  58. #endif // Yinku
  59. sieve(MAXN);
  60. while(~scanf("%d%d", &q, &n)) {
  61. GetFactor(n);
  62. atop = 0;
  63. for(int i = 1; i <= ptop; ++i) {
  64. if(check(n, p[i]))
  65. ans[++atop] = p[i];
  66. }
  67. printf("%d\n", atop);
  68. for(int i = 1; i <= atop; ++i)
  69. printf("%d%c", ans[i], " \n"[i == atop]);
  70. }
  71. return 0;
  72. }

直接上BSGS的话,假如这样的p有10000个就比较麻烦。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. int q, n;
  5. const int MAXN = 1e7 + 5;
  6. int p[MAXN], ptop;
  7. bool np[MAXN];
  8. void sieve(int n) {
  9. np[1] = 1;
  10. for(int i = 2; i <= n; i++) {
  11. if(!np[i])
  12. p[++ptop] = i;
  13. for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
  14. np[t] = 1;
  15. if(i % p[j] == 0)
  16. break;
  17. }
  18. }
  19. }
  20. int qpow(ll x, int n, int p) {
  21. ll res = 1;
  22. while(n) {
  23. if(n & 1)
  24. res = res * x % p;
  25. x = x * x % p;
  26. n >>= 1;
  27. }
  28. return res;
  29. }
  30. unordered_map<int,int> M;
  31. int bsgs(int a,int b,int n,int k=1,int t=0){
  32. /*if(b==1)
  33. return 0;*/
  34. M.clear();
  35. int m=ceil(sqrt(n));
  36. ll s=b;
  37. for(int i=0;i<m;++i,s=s*a%n){
  38. M[s]=i;
  39. }
  40. s=k;
  41. k=qpow(a,m,n);
  42. for(ll i=1;i<=m;++i){
  43. s=s*k%n;
  44. if(M.count(s))
  45. return i*m-M[s]+t;
  46. }
  47. return -1;
  48. }
  49. int ans[MAXN], atop;
  50. int check(int n, int p) {
  51. if(qpow(q, n, p) != 1)
  52. return 0;
  53. int res=bsgs(q,1,p);
  54. if(res==-1||res==n)
  55. return 1;
  56. return 0;
  57. }
  58. int main() {
  59. #ifdef Yinku
  60. freopen("Yinku.in", "r", stdin);
  61. #endif // Yinku
  62. sieve(MAXN);
  63. while(~scanf("%d%d", &q, &n)) {
  64. atop = 0;
  65. for(int i = 1; i <= ptop; ++i) {
  66. if(check(n, p[i]))
  67. ans[++atop] = p[i];
  68. }
  69. printf("%d\n", atop);
  70. for(int i = 1; i <= atop; ++i)
  71. printf("%d%c", ans[i], " \n"[i == atop]);
  72. }
  73. return 0;
  74. }

SCUT - 485 - 质因数计数 - 原根的更多相关文章

  1. SCUT - 11 - 被钦定的选手 - 质因数分解

    https://scut.online/p/11 T了好多次,还想用mutimap暴力分解每个数的质因数.后来记录每个数的最小质因子过了. #include <bits/stdc++.h> ...

  2. SCUT - 243 - 宝华复习 - 二分 - 桶计数

    https://scut.online/p/243 这道题唯一难点在于如何快速确定m合法.可以统计滑动窗口中已有元素的数量. #include<bits/stdc++.h> using n ...

  3. 数论入门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}p ...

  4. 【BZOJ】【1211】【HNOI2004】树的计数

    Prufer序列+组合数学 嗯哼~给定每个点的度数!求树的种数!那么很自然的就想到是用prufer序列啦~(不知道prufer序列的……自己再找找资料吧,这里就不放了,可以去做一下BZOJ1005明明 ...

  5. 【poj1284-Primitive Roots】欧拉函数-奇素数的原根个数

    http://poj.org/problem?id=1284 题意:给定一个奇素数p,求p的原根个数. 原根: { (xi mod p) | 1 <= i <= p-1 } is equa ...

  6. 原根求解算法 && NTT算法

    原根求解算法: 获取一个数\(N\)的原根\(root\)的算法 #include<bits/stdc++.h> #define ll long long #define IL inlin ...

  7. 简单数论之整除&质因数分解&唯一分解定理

    [整除] 若a被b整除,即a是b的倍数,那么记作b|a("|"是整除符号),读作"b整除a"或"a能被b整除".b叫做a的约数(或因数),a ...

  8. [总结]数论和组合计数类数学相关(定理&证明&板子)

    0 写在前面 0.0 前言 由于我太菜了,导致一些东西一学就忘,特开此文来记录下最让我头痛的数学相关问题. 一些引用的文字都注释了原文链接,若侵犯了您的权益,敬请告知:若文章中出现错误,也烦请告知. ...

  9. BZOJ2219数论之神——BSGS+中国剩余定理+原根与指标+欧拉定理+exgcd

    题目描述 在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出 ...

随机推荐

  1. Cassandra 数据一致性

    基本概念 一致性: 在分布式系统中的所有数据备份,在同一时刻是否同样的值 QUORUM: 是一个可以计算的数字,对数据一致性起重要作用 Node: 主要用来存储数据 Data Center: 数据中心 ...

  2. ssh复制公钥成功后仍需输入密码

    1,网上说权限问题 登录流程: 被登录机器的文件权限: //用户权限 chmod 700 /home/username //.ssh文件夹权限 chmod 700 ~/.ssh/ // ~/.ssh/ ...

  3. JPA学习(四、JPA_映射关联关系)

    框架学习之JPA(四) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...

  4. 命令行创建 vue 项目(仅用于 Vue 2.x 版本)

    1 .安装 Node.js 和 npm ( 验证安装成功输入下图 1 命令行可得 2:输入命令行 3 可得 4 即安装成功) 2.安装全局 webpack (安装依照下图输入命令行 1 耐心等待至到出 ...

  5. Python黑科技:在家远程遥控公司电脑,python+微信一键连接!

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管理 Windows10操作系统的开 ...

  6. Spring Boot教程(十九)RESTful API单元测试

    下面针对该Controller编写测试用例验证正确性,具体如下.当然也可以通过浏览器插件等进行请求提交验证. @RunWith(SpringJUnit4ClassRunner.class) @Spri ...

  7. Spring Cloud云架构 - SSO单点登录之OAuth2.0 登出流程(3)

    上一篇我根据框架中OAuth2.0的使用总结,画了一个根据用户名+密码实现OAuth2.0的登录认证的流程图,今天我们看一下logout的流程: /** * 用户注销 * @param accessT ...

  8. eclipse代码自动补全设置

    1.说明 eclipse安装好了之后,在编辑框中输入某个英文字符,默认不自动弹出自动代码选择框,需要手动按下 Alt + / 或者输入的字符为 .  才弹出代码自动补全框.其实eclipse是可以设置 ...

  9. springboot 配置访问本地图片

    spring.mvc.static-path-pattern=/image/** spring.resources.static-locations=file:D://image/

  10. Electron-Vue工程初始化,以及需要掌握的相关知识

    1.安装nodejs 下载地址:http://nodejs.cn/ 需要重启系统 2.安装electron npm install electron -g 3.安装vue npm install vu ...