x^A=B(mod C)的解 (离散对数与原根)
来源:互联网 发布:软件企业即征即退政策 编辑:程序博客网 时间:2024/06/06 14:20
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3930
题意:给定同余式,求它在内的所有解,其中总是素数。
分析:解本同余式的步骤如下
(1)求模的一个原根
(2)利用Baby Step Giant Step求出一个,使得,因为为素数,所以有唯一解。
(3)设,这样就有,其中,那么得到。
(4)求出所有的,可以知道一共有个解,我们求出所有的,然后排个序即可。
代码:
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#include <math.h>#include <bitset>#include <map>using namespace std;typedef long long LL;const int N = 1000005;/**以下为求原根部分 */bitset<N> prime;int p[N],pri[N];int k,cnt;void isprime(){ prime.set(); for(int i=2; i<N; i++) { if(prime[i]) { p[k++] = i; for(int j=i+i; j<N; j+=i) prime[j] = false; } }}void Divide(LL n){ cnt = 0; LL t = (LL)sqrt(1.0*n); for(int i=0; p[i]<=t; i++) { if(n%p[i]==0) { pri[cnt++] = p[i]; while(n%p[i]==0) n /= p[i]; } } if(n > 1) pri[cnt++] = n;}LL multi(LL a,LL b,LL m){ LL ans = 0; a %= m; while(b) { if(b & 1) { ans = (ans + a) % m; b--; } b >>= 1; a = (a + a) % m; } return ans;}LL quick_mod(LL a,LL b,LL m){ LL ans = 1; a %= m; while(b) { if(b&1) { ans = multi(ans,a,m); b--; } b >>= 1; a = multi(a,a,m); } return ans;}LL broot(LL p){ Divide(p-1); for(int g=2 ;; g++) { bool flag = true; for(int i=0; i<cnt; i++) { LL t = (p - 1) / pri[i]; if(quick_mod(g,t,p) == 1) { flag = false; break; } } if(flag) return g; }}/**以上为求原根部分 *//** 以下为Baby_Step */LL gcd(LL a,LL b){ return b ? gcd(b,a%b):a;}void extend_Euclid(LL a,LL b,LL &x,LL &y){ if(b == 0) { x = 1; y = 0; return; } extend_Euclid(b,a%b,x,y); LL tmp = x; x = y; y = tmp - (a / b) * y;}LL Inv(LL a,LL p){ return quick_mod(a,p-2,p);}LL Baby_Step(LL A,LL B,LL C){ map<LL,int> mp; LL M = ceil(sqrt(1.0*C)); LL t = Inv(quick_mod(A,M,C),C); LL ans = 1; for(int i=0; i<M; i++) { if(!mp.count(ans)) mp[ans] = i; ans = multi(ans,A,C); } for(int i=0; i<M; i++) { if(mp.count(B)) return i * M + mp[B]; B = multi(B,t,C); } return -1;}/** 以上为Baby_Step */LL ans[1005];void Work(LL A,LL B,LL C){ LL root = broot(C); LL t1 = Baby_Step(root,B,C); LL t2 = C - 1; LL d = gcd(A,t2); if(t1 % d) { puts("-1"); return; } LL x,y; extend_Euclid(A,t2,x,y); t2 /= d; t1 /= d; ans[0] = (x * t1 % t2 + t2) % t2; for(int i=1; i<d; i++) ans[i] = ans[i-1] + t2; for(int i=0; i<d; i++) ans[i] = quick_mod(root,ans[i],C); sort(ans,ans+d); for(int i=0; i<d; i++) cout<<ans[i]<<endl;}int main(){ int T = 1; LL A,B,C; isprime(); while(cin>>A>>C>>B) { printf("case%d:\n",T++); Work(A,B,C); } return 0;}
- x^A=B(mod C)的解 (离散对数与原根)
- 离散对数(关于方程x^A=B(mod C)的解)
- 求同余方程x^A=B(mod m)的解个数(原根与指标)
- (离散对数与原根)
- 原根与离散对数
- 解一类A^x=B(mod C)(C是质数)的方程 (BSGS)
- X^a mod b=c 式子中求所有的X(b总是质数)
- 解一类x^a = b (mod p)的方程
- 离散对数和原根
- BSGS+原根+离散对数
- 求解x=a^b(mod m)
- 求解x=a^b(mod m)
- A^B mod C
- A^B mod C
- A^B mod C
- HDU 2815 Mod Tree 解a^x = b(mod n)非互质
- BZOJ 2301 Problem B(x属于[a,b],y属于[c,d]满足gcd(x,y)=k的(x,y)的有序对数)
- A^B mod C的分治思想
- 黑马程序员 Java自学总结八 面向对象三个特征之多态
- 走向并行系列之-使用ForkManager编写多进程程序
- uImage的制作
- winfor应用程序打印报表清单
- 批量修改文件名的方法
- x^A=B(mod C)的解 (离散对数与原根)
- 黑马程序员 Java自学总结九 内部类
- 从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法
- Java RMI-远程方法调用
- 在hibernate 中用 sql ,并用别名出现列找不到的情况
- csapp2e 家庭作业 6.47
- XDoclet详解
- poj 1364 King
- 程序员的奋斗史(二十六)——迷失的朋友