原根-快速求解一个数的原根
来源:互联网 发布:java随机生成游戏昵称 编辑:程序博客网 时间:2024/06/10 12:02
1.原根定义
欧拉定理(也称费马-欧拉定理或欧拉函数定理)是一个关于同余的性质。欧拉定理表明,若为正整数,且互素(即),则
2.如何求解:
一、枚举
从2开始枚举,然后暴力判断g^(P-1) = 1 (mod P)是否当且当指数为P-1的时候成立
二、讲究方法
例如求任何一个质数x的任何一个原根,一般就是枚举2到x-1,并检验。有一个方便的方法就是,求出x-1所有不同的质因子p1,p2...pm,对于任何2<=a<=x-1,判定a是否为x的原根,只需要检验a^((x-1)/p1),a^((x-1)/p2),...a^((x-1)/pm)这m个数中,是否存在一个数mod x为1,若存在,a不是x的原根,否则就是x的原根。
原来的复杂度是O(P-1),现在变成O(m)*log(P-1)m为x-1质因子的个数。很明显质因子的个数远远小于x-1。
证明可用欧拉定理和裴蜀定理:
裴蜀定理
说明了对任何整数a、b和它们的最大公约数d,关于未知数x和y的线性丢番图方程(称为裴蜀等式):
ax + by = m
有解当且仅当m是d的倍数。裴蜀等式有解时必然有无穷多个整数解,每组解x、y都称为裴蜀数,可用辗转相除法求得。
例如,12和42的最大公因子是6,则方程12x + 42y = 6有解。事实上有(-3)×12 + 1×42 = 6及4×12 + (-1)×42 = 6。
特别来说,方程 ax + by = 1 有解当且仅当整数a和b互素。
裴蜀等式也可以用来给最大公约数定义:d其实就是最小的可以写成ax + by形式的正整数。这个定义的本质是整环中“理想”的概念。因此对于多项式整环也有相应的裴蜀定理。
证明
若存在,那么显然的事情否则,假设存在一个t<phi(x)=x-1使得a^t = 1 (mod x)那么由裴蜀定理,一定存在一组k,r使得kt=(x-1)r+gcd(t,x-1)而由欧拉定理有,a^(x-1) = 1 (mod x)于是1 = a^(kt) = a^(xr-r+gcd(t,x-1)) = a^gcd(t,x-1) (mod x)而t<x-1故gcd(t,x-1)<x-1又gcd(t,x-1)|x-1 于是gcd(t,x-1)必整除(x-1)/p1,(x-1)/p2...(x-1)/pm其中至少一个,设其一为(x-1)/pi那么a^((x-1)/pi) = (a^gcd(t,x-1))^s = 1^s = 1 (mod x)这与假设矛盾
代码:
来至http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1135的一道题目:
题目
输入1个质数P(3 <= P <= 10^9)
输出P最小的原根。
解答
#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;int P;const int NUM = 32170;int prime[NUM/4];bool f[NUM];int pNum = 0;void getPrime()//线性筛选素数{for (int i = 2; i < NUM; ++ i){if (!f[i]){f[i] = 1;prime[pNum++] = i;}for (int j = 0; j < pNum && i*prime[j] < NUM; ++ j){f[i*prime[j]] = 1;if (i%prime[j] == 0){break;}}}}__int64 getProduct(int a,int b,int P)//快速求次幂mod{__int64 ans = 1;__int64 tmp = a;while (b){if (b&1){ans = ans*tmp%P;}tmp = tmp*tmp%P;b>>=1;}return ans;}bool judge(int num)//求num的所有的质因子{int elem[1000];int elemNum = 0;int k = P - 1;for (int i = 0; i < pNum; ++ i){bool flag = false;while (!(k%prime[i])){flag = true;k /= prime[i];}if (flag){elem[elemNum ++] = prime[i];}if (k==1){break;}if (k/prime[i]<prime[i]){elem[elemNum ++] = prime[i];break;}}bool flag = true;for (int i = 0; i < elemNum; ++ i){if (getProduct(num,(P-1)/elem[i],P) == 1){flag = false;break;}}return flag;}int main(){getPrime();while (cin >> P){for (int i = 2;;++i){if (judge(i)){cout << i<< endl;break;}}}return 0;}
- 原根-快速求解一个数的原根
- 原根(详解+代码实现+例题+快速求解一个数的原根)
- 51Nod 1135-原根(快速求解一个素数的原根)
- 51Nod 1135-原根(快速求解一个素数的原根)
- 原根的求解证明 附代码
- poj 1284 求一个数的原根个数
- HDU 4992 求一个数的所有原根
- 【原】求解一个数的所有素数因数(因数分解)
- 模为奇素数的原根求解
- 原根
- 原根
- 原根
- 原根
- 原根
- 原根
- 原根
- 原根
- 原根
- 向服务器上传文件
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- OpenCV实现人脸识别——EigenFace特征脸法
- Hadoop常用命令
- 马屁股决定航天飞机
- 原根-快速求解一个数的原根
- 三个精灵说真话假话的判断难题
- C++中四种类型转换方式
- OpenCV 第七章 单路直方图
- GifView——Android显示GIF动画
- Linux常用命令
- 企业即时通讯软件一个人留在北京
- scabl: Monads in Scala Part Three: Lisst[A]
- hdu1503