离散对数和原根
来源:互联网 发布:离线基站数据库 300万 编辑:程序博客网 时间:2024/05/16 07:24
原根与阶
阶定义
设
当
简单性质
ax≡1⇔ordm(a)∣x ordm(a)∣ϕ(m) a0,a1,…,aordm(a)−1 构成摸m的既约剩余系.ax≡ay(mod m)⇔x≡y(mod ordm(a)) ordm(ad)=ordm(a)(ordm(a),d) (利用这个性质可以求出所有原根)- m(若存在原根)的原根数目为
ϕ(ϕ(m)) . n有原根⇔n=2,4,pe,2pe(p为奇素数) .- 设
ϕ(m)=pr11pr22…prkk ,则g是m 的原根当且仅当对与所有的pi .gϕ(m)pi≠1(mod m)
求阶和原根的方法
上面的性质是非常容易证明的.随便找一本数论书籍都会有详细的证明.由上面的性质我们可以得到一个相对简单的求阶和原根的方法(暴力)
- 阶: 我门可以对m先分解因子,设
m=pr11pr22…prkk ,然后将ri 逐个相减记为p 直到再减一个之后ap≠1 - 原根: 这个就更加暴力了,我们可以用性质8逐一枚举与
m 互素的数然后对分解式进行验证就好.
这里有一份51nod模板题1135的代码
#include <cstdio>#include <iostream>#include <vector>#include <queue>#include <algorithm>#include<cmath>#include <cstring>#include <map>#include <iomanip>#define fi first#define se second#define INF 0x3f3f3f3fusing namespace std;const int MOD = 1e9+7;const int MAX_P = 2e4+10;const int maxn =2e5+10;const int MAX_V = 5e5+10;const int maxv = 1e6+10;typedef long long LL;typedef long double DB;typedef pair<int,int> Pair;int p;int prime[maxn],cnt;int factor[maxn],fact_cnt;void init_prime(){ memset(prime,0,sizeof(prime)); cnt = 0; for(int i = 2 ; i<maxn ; ++i){ if(!prime[i]){ prime[cnt++] = i; } for(int j =0 ; j<cnt && prime[j]*i<maxn ; ++j){ prime[prime[j]*i] = 1; if(i % prime[j] == 0)break; } }}LL power_mod(LL x,LL n,LL mod){ LL res =1; while (n) { if(n & 1)res = res*x % mod; x = x*x % mod; n >>= 1; } return res;}void get_fact(int n){ fact_cnt = 0; for(int i = 0 ; i< cnt && prime[i]*prime[i] <=n ; ++i ){ if(n % prime[i] == 0){ factor[fact_cnt++] = prime[i]; while (n%prime[i] == 0)n/=prime[i]; } } if(n!=1)factor[fact_cnt++] = n;}bool check(int g){ for(int i=0 ; i<fact_cnt ; ++i) if(power_mod(g,(p-1)/factor[i],p) ==1)return false; return true;}int proot(int p){ get_fact(p-1); for(int i=2 ; i<p ; ++i) if(check(i))return i;}int main(int argc, char const *argv[]) { init_prime(); cin>>p; std::cout << proot(p) << '\n'; return 0;}
离散对数
bsgs algorithm
大步小步算法,这个算法有一定的局限性,只有当
原理
简单说一下它的原理.其实由上面的性质,我们知道
扩展大步小步
上面的过程能求离散对数的前提是
由于模方程
模板题spoj MOD - Power Modulo Inverted
#include <cstdio>#include <iostream>#include <vector>#include <queue>#include <algorithm>#include<cmath>#include <cstring>#include <map>#define fi first#define se second#define INF 0x3f3f3f3fusing namespace std;const int MOD = 1e9+7;const int MAX_P = 2e4+10;const int maxn =500+10;const int MAX_V = 5e5+10;const int maxv = 1e6+10;typedef long long LL;typedef pair<int,int> Pair;LL power_mod(LL x,LL n, int mod){ LL res =1; while (n) { if(n&1)res = res*x % mod; x = x*x %mod; n >>=1; } return res;}LL bsgs(LL A,LL C,LL mod){ A %= mod;C %= mod; if(C==1)return 0; LL cnt =0; LL tmp = 1; for(LL g = __gcd(A,mod) ; g != 1 ; g = __gcd(A,mod)){ if(C % g)return -1;//不能整除 C /=g ; mod/=g ; tmp = tmp*A/g%mod; ++cnt; if(C == tmp)return cnt; } //大步小步a^xa^cnt=C (mod m)a^cnt = tmp; LL T = (LL)sqrt(0.5+mod); LL b = C; map<LL,LL> hash; hash[b] = 0; for(int i=1 ; i<=T ; ++i){ b = b*A%mod;//当mod为LL时注意溢出 hash[b] = i; } A = power_mod(A,T,mod); for(int u =1 ; u<=T ; ++u){ tmp = tmp*A %mod; if(hash.count(tmp))return u*T-hash[tmp]+cnt; } return -1;}int main(int argc, char const *argv[]) { LL x,y,z,k; while (scanf("%lld%lld%lld",&x,&z,&k ) && z) { y = bsgs(x,k,z); if(y==-1)std::cout << "No Solution" << '\n'; else std::cout << y << '\n'; } return 0;}
0 0
- 离散对数和原根
- (离散对数与原根)
- 原根与离散对数
- BSGS+原根+离散对数
- 本原根和离散对数
- 高次同余笔记(三):离散对数和原根
- sgu261:Discrete Roots(原根+离散对数+扩展欧几里得)
- hdu 5377 Root 原根+离散对数+扩展欧几里得
- [BZOJ]2219 数论之神 离散对数 + 原根
- x^A=B(mod C)的解 (离散对数与原根)
- SGU261 一些数学知识入门与应用结合 原根 快速幂 离散对数 扩展欧几里得 单边元模线性方程
- 离散对数和椭圆曲线加密原理
- hdu3930 broot 离散k次根 ,离散对数
- 离散对数问题
- 离散对数加密算法
- 离散对数问题
- POJ 2417 离散对数
- HDU 2815 离散对数
- 使用WebMagic 编写 java 网络爬虫
- 第八章 数组
- JavaWeb开发之JSP隐式对象(二)
- Swift服务器入门+ReactJS代码示范:如何在内存中建立高性能索引
- 杭电ACM 1004 Let the Balloon Rise
- 离散对数和原根
- IMWeb训练营作业——使用vue完成todolist
- [LeetCode]238. Product of Array Except Self
- 集合框架-Collection集合-3
- CASIO DC-850 DATA-CAL Manual (操作使用方法)
- 9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路
- 物联网时代来了,大数据也终于有了用武之地
- uva 572
- 字符串算法常用的操作