N次剩余 最基础的laji入门
之前说道模意义下开根号
貌似就剩这一个锅了
今天就mie了她
Question:
给定方程 x ^ n ≡ a (mod p) 求x (p为质数)
Solution:
仍然考虑枚举 发现无法优化
考虑拆分 发现左边全是x没法拆...
由于我们先解决了离散对数问题 所以考虑转化
把x和a都转化成指数形式就可以解决
于是问题就变为g^(bn) ≡ g^c(mod p)
由于p是质数 所以如果欧拉定理优化就是bn≡c(mod p-1)
先不考虑g的问题 如果知道c就直接逆元就好了
然后如果知道g c也可以由BSGS求出来
所以问题转化为 对于一个质数p 求出一个g 使得g的0~p-2次方与1~p-1一一对应
我们给这个东西起名为 原根
总体来说也是一种暴力 然后根据玄学证明(实际还是比较简单的,跟上面过程差不多) 可以得出
验证p-1所有的素因子p[i]是否都没有g ^ (p - 1 / p[i]) ≡ 1 等价于验证所有[1~p]的数是否完全剩余
Code:并没有代码
(啪!)
Code by 学姐
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <ctime> 7 //#define ivorysi 8 #define MAXN 100005 9 #define eps 1e-7 10 #define mo 974711 11 using namespace std; 12 typedef long long int64; 13 typedef unsigned int u32; 14 typedef double db; 15 int64 A,B,C,G,eu; 16 int64 ans[MAXN],tmp[MAXN],R,L[MAXN],cntL; 17 int M; 18 struct node { 19 int next,num; 20 int64 hsh; 21 }E[MAXN]; 22 int head[mo + 5],sumE; 23 int64 fpow(int64 x,int64 c,int64 MOD) { 24 int64 res = 1,t = x; 25 while(c) { 26 if(c & 1) res = res * t % MOD; 27 t = t * t % MOD; 28 c >>= 1; 29 } 30 return res; 31 } 32 int primitive_root(int64 P,int64 eu) { 33 static int64 factor[1005]; 34 int cnt = 0; 35 int64 x = eu; 36 for(int64 i = 2 ; i <= x / i ; ++i) { 37 if(x % i == 0) { 38 factor[++cnt] = i; 39 while(x % i == 0) x /= i; 40 } 41 } 42 if(x > 1) factor[++cnt] = x; 43 for(int G = 2 ; ; ++G) { 44 for(int j = 1 ; j <= cnt ; ++j) { 45 if(fpow(G,eu / factor[j],P) == 1) goto fail; 46 } 47 return G; 48 fail:; 49 } 50 } 51 int64 gcd(int64 a,int64 b) { 52 return b == 0 ? a : gcd(b,a % b); 53 } 54 void ex_gcd(int64 a,int64 b,int64 &x,int64 &y) { 55 if(b == 0) { 56 x = 1,y = 0; 57 } 58 else { 59 ex_gcd(b,a % b,y,x); 60 y -= a / b * x; 61 } 62 } 63 int64 Inv(int64 num,int64 MOD) { 64 int64 x,y; 65 ex_gcd(num,MOD,x,y); 66 x %= MOD;x += MOD; 67 return x % MOD; 68 } 69 void add(int u,int64 val,int num) { 70 E[++sumE].hsh = val; 71 E[sumE].next = head[u]; 72 E[sumE].num = num; 73 head[u] = sumE; 74 } 75 void Insert(int64 val,int num) { 76 int u = val % mo; 77 for(int i = head[u] ; i ; i = E[i].next) { 78 if(val == E[i].hsh) { 79 E[i].num = num; 80 return; 81 } 82 } 83 add(u,val,num); 84 } 85 int Query(int64 val) { 86 int u = val % mo; 87 for(int i = head[u] ; i ; i = E[i].next) { 88 if(val == E[i].hsh) { 89 return E[i].num; 90 } 91 } 92 return -1; 93 } 94 int BSGS(int64 A,int64 C,int64 P) { 95 memset(head,0,sizeof(head));sumE = 0; 96 int64 S = sqrt(P); 97 int64 t = 1,invt = 1,invA = Inv(A,P); 98 99 for(int i = 0 ; i < S ; ++i) { 100 if(t == C) return i; 101 Insert(invt * C % P,i); 102 t = t * A % P; 103 invt = invt * invA % P; 104 } 105 int64 tmp = t; 106 for(int i = 1 ; i * S < P ; ++i) { 107 int x = Query(tmp); 108 if(x != -1) { 109 return i * S + x; 110 } 111 tmp = tmp * t % P; 112 } 113 } 114 bool Process(int64 A,int64 C,int64 P,int k) { 115 int64 MOD = 1,g; 116 for(int i = 1 ; i <= k ; ++i) MOD *= P; 117 cntL = 0; 118 if(C % MOD == 0) { 119 int64 T = (k - 1) / A + 1; 120 L[++cntL] = 0; 121 if(T < k) { 122 int64 num = fpow(P,T,MOD); 123 for(int i = 1 ; i * num < MOD ; ++i) L[++cntL] = i * num; 124 } 125 } 126 else if(g = gcd(C % MOD,MOD) != 1){ 127 int64 x = C % MOD; 128 int c = 0; 129 while(x % P == 0) ++c,x /= P; 130 if(c % A != 0) return false; 131 G = primitive_root(MOD / (C / x),eu / (C / x)); 132 eu /= C / x; 133 int e = BSGS(G,x,MOD / (C / x)); 134 g = gcd(A,eu); 135 if(e % g != 0) return false; 136 e /= g; 137 int64 s = Inv(A / g,eu / g) * e % (eu / g); 138 L[++cntL] = s; 139 while(1) { 140 if((L[cntL] + eu / g) % (eu * (C / x)) == L[1]) break; 141 L[cntL + 1] = L[cntL] + eu / g; 142 ++cntL; 143 } 144 for(int i = 1 ; i <= cntL ; ++i) { 145 L[i] = fpow(G,L[i],MOD) * fpow(P,c / A,MOD) % MOD; 146 } 147 } 148 else { 149 int e = BSGS(G,C % MOD,MOD); 150 g = gcd(A,eu); 151 if(e % g != 0) return false;e /= g; 152 int s = Inv(A / g,eu / g) * e % (eu / g); 153 L[++cntL] = s; 154 while(1) { 155 if(L[cntL] + eu / g >= eu) break; 156 L[cntL + 1] = L[cntL] + eu / g; 157 ++cntL; 158 } 159 for(int i = 1 ; i <= cntL ; ++i) L[i] = fpow(G,L[i],MOD); 160 } 161 if(!cntL) return false; 162 if(!M) { 163 M = cntL; 164 for(int i = 1 ; i <= M ; ++i) ans[i] = L[i]; 165 sort(ans + 1,ans + M + 1); 166 M = unique(ans + 1,ans + M + 1) - ans - 1; 167 R = MOD; 168 return true; 169 } 170 int tot = 0; 171 for(int i = 1 ; i <= M ; ++i) { 172 for(int j = 1 ; j <= cntL ; ++j) { 173 tmp[++tot] = (R * Inv(R,MOD) % (R * MOD) * (L[j] - ans[i]) + ans[i]) % (R * MOD); 174 tmp[tot] = (tmp[tot] + R * MOD) % (R * MOD); 175 } 176 } 177 R *= MOD; 178 sort(tmp + 1,tmp + tot + 1); 179 tot = unique(tmp + 1,tmp + tot + 1) - tmp - 1; 180 for(int i = 1 ; i <= tot ; ++i) ans[i] = tmp[i]; 181 M = tot; 182 return true; 183 } 184 void Solve() { 185 M = 0; 186 if(B % 2 == 0) { 187 int64 Now = 2;B /= 2; 188 if(C & 1) ans[++M] = 1; 189 else ans[++M] = 0; 190 191 while(B % 2 == 0) { 192 B /= 2; 193 Now *= 2; 194 int t = 0; 195 for(int i = 1 ; i <= M ;++i) { 196 if(fpow(ans[i],A,Now) == C % Now) tmp[++t] = ans[i]; 197 if(fpow(ans[i] + Now / 2,A,Now) == C % Now) tmp[++t] = ans[i] + Now / 2; 198 } 199 for(int i = 1 ; i <= t ; ++i) ans[i] = tmp[i]; 200 if(!t) goto fail; 201 M = t; 202 } 203 R = Now; 204 sort(ans + 1,ans + M + 1); 205 M = unique(ans + 1,ans + M + 1) - ans - 1; 206 } 207 for(int64 i = 3 ; i <= B / i ; ++i) { 208 if(B % i == 0) { 209 eu = (i - 1); 210 B /= i; 211 int num = i,cnt = 1; 212 while(B % i == 0) { 213 B /= i;eu *= i;num *= i;++cnt; 214 } 215 G = primitive_root(num,eu); 216 if(!Process(A,C,i,cnt)) goto fail; 217 } 218 } 219 if(B > 1) { 220 eu = B - 1; 221 G = primitive_root(B,eu); 222 if(!Process(A,C,B,1)) goto fail; 223 } 224 if(M == 0) goto fail; 225 sort(ans + 1,ans + M + 1); 226 for(int i = 1 ; i <= M ; ++i) { 227 printf("%d%c",ans[i]," \n"[i == M]); 228 } 229 return; 230 fail: 231 puts("No Solution"); 232 } 233 int main() { 234 #ifdef ivorysi 235 freopen("f1.in","r",stdin); 236 #endif 237 int T; 238 scanf("%d",&T); 239 while(T--) { 240 scanf("%lld%lld%lld",&A,&B,&C); 241 Solve(); 242 } 243 }
View Code
转载于:https://www.cnblogs.com/yuyanjiaB/p/9803963.html
N次剩余 最基础的laji入门相关推荐
- 《零基础掌握 Python 入门到实战》笔记
Python 零基础掌握 Python 入门到实战笔记 文章目录 Python 内置对象类型 基本交互语句 常用内置函数 整数与浮点数 基本数学运算 高级数学运算 字符串 序列 索引 切片 成员函数 ...
- 零基础Python培训入门 教你认识下这些基础内容
Python编程语言为什么近些年这么火?从它本身的语言特性来看,Python编程简单而且直接,适合初学编程者,让初学者能够专注于编程逻辑,而不是在不流通的语法细节上感到困惑.零基础Python培训中心 ...
- python编程基础语法-Python编程基础语法快速入门
1. 课程咨询加老师助理微信:助理1微信: chenjinglei88 ,助理2微信: omf6757 2. 决定购买并想得到陈敬雷老师亲自指导(课程或自己项目难题均可)加老师微信: chenjing ...
- 零基础编程入门python视频-Python编程零基础小白快速入门完整全系列精品课
1. 课程咨询加老师助理微信:助理1微信: chenjinglei88 ,助理2微信: omf6757 2. 决定购买并想得到陈敬雷老师亲自指导(课程或自己项目难题均可)加老师微信: chenjing ...
- 【Python基础】快速入门Python(讲解、习题)
0.导语 Python是一种跨平台的计算机程序设计语言.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的 ...
- Oracle数据库基础教程:入门其实很简单
为什么80%的码农都做不了架构师?>>> Oracle数据库基础教程:入门其实很简单 Oracle数据库系统是目前最流行的客户/服务器数据库之一.本文集从初学者的角度出发,由浅 ...
- 19年8月 字母哥 第一章 spring boot 2.x基础及概念入门 这里全部看完了 热部署没出来 第二章在前面2页 用热点公司网不行
http://springboot.zimug.com/1233100 文档 http://www.zimug.com/page/5 字母哥个人博客 11111 第一章 spring bo ...
- Java零基础并发编程入门
Java零基础并发编程入门 并发编程主要包括: 线程,同步,future,锁,fork/join, volatile,信号量,cas(原子性,可见性,顺序一致性),临界性,分布式 了解基础: JMM: ...
- plc维修入门与故障处理实例_电气控制基础+PLC编程入门+工程应用实例
以S7-300/400PLC为主线 电气控制基础+PLC编程入门+工程应用实例 点击图片 购买 编辑推荐1.西门子S7300/400PLC应用广.市场占有率高 2.本书通过大量的实验案例和真实的工程 ...
- python基础教程博客_Python基础教程_Python入门知识
Python基础教程频道为编程初学者提供入门前的所有基础知识,必须要掌握的一些PYTHON基础语法语句,基本的数据类型. 让大家可以更快速.更容易理解的的方式掌握Python编程所需要的基础知识,灵活 ...
最新文章
- HikariPool 连接池问题
- hdu5386(暴力)
- OpenCASCADE:Foundation Classes数据类型
- react Native 环境安装配置——图解版一目了然
- htaccess配置文件是什么
- Texlive source
- INIT: vesion 2.88 booting
- UAT测试和SIT测试
- Other | 十招教你找到海量PPT模板
- 这些曾盛极一时的经典软件,现在再看,还是记忆犹新
- 上海师大计算机科学与技术,上海师大计算机科学与技术专业本科文凭、国家承认可查证书...
- SolidWorks2021导出带材质的OBJ文件
- linux解密shadow_Linux /etc/shadow(影子文件)内容解析(超详细)
- CSS之vmin和vmax
- hdu4565 so easy 矩阵
- vue打开新的标签页
- Linux驱动开发之常见error汇总
- 如何使用kodi Mac安装中文插件
- Python自动生成ffmpeg转码HEVC (X265,H265) 命令
- pl/sql模拟登录并获取Oracle ebs职责