求质数的原根

#include <bits/stdc++.h>
using namespace std;
const int N=1000005;
int P, cnt, pcnt, p[N], pr[N];
bool np[N];
typedef long long ll;
int gcd(int a, int b) { return b?gcd(b, a%b):a; }
int ipow(int a, int b) { int x=1; for(; b; b>>=1, a=(ll)a*a%P) if(b&1) x=(ll)x*a%P; return x; }
bool check(int d) {
	if(gcd(d, P)!=1) return 0;
	for(int i=1; i<=cnt; ++i) if(ipow(d, (P-1)/pr[i])==1) return 0;
	return 1;
}
void init() {
	for(int i=2; i<N; ++i) {
		if(!np[i]) p[++pcnt]=i;
		for(int j=1; j<=pcnt; ++j) {
			int t=i*p[j]; if(t>=N) break; np[t]=1;
			if(i%p[j]==0) break;
		}
	}
}
void get() {
	int temp=P-1;
	for(int i=1; i<=pcnt && p[i]*p[i]<=temp; ++i) if(temp%p[i]==0) { while(temp%p[i]==0) temp/=p[i]; pr[++cnt]=p[i]; }
	if(temp>1) pr[++cnt]=temp;
}
int main() {
	scanf("%d", &P);
	init();
	get();
	for(int i=2; i<P; ++i) if(check(i)) { printf("%d\n", i); break; }
	return 0;
}

  

如果$(a, m)=1$,那么容易得到$\delta_{m} (a) | \varphi(m)$,因此我们只需要检测$m$的约数即可,可是复杂度很高= =。

更特殊的,假如$m$是质数,那么我们只需要检测$\frac{\varphi(m)}{p_1}, \frac{\varphi(m)}{p_2}, \cdots, \frac{\varphi(m)}{p_k}$($p_i$表示$m$的不同的质因子)即可。

证明:

如果检测出来时,显然$a$不是原根。否则,我们没有检测出来,即$a$不是$m$的原根,令$d<\varphi(a)$使得$a^d \equiv 1 \pmod{m}$

因为$d<\varphi(m)$,所以$(d, \varphi(m)) < \varphi(m)$。

而又因为$(d, \varphi(m)) | \varphi(m)$, 所以$(d, \varphi(m))$必整除$\frac{\varphi(m)}{p_1}, \frac{\varphi(m)}{p_2}, \cdots, \frac{\varphi(m)}{p_k}$中至少一个,令其中一个为$\frac{\varphi(m)}{p_i}$。

由于存在$x, y$使得$dx+\varphi(m)y = (d, \varphi(m))$,所以$a^{(d, \varphi(m))} \equiv (a^d)^x + (a^{\varphi(m)})^y \equiv 1 \pmod{m}$。

所以$a^{\frac{\varphi(m)}{p_i}} = (a^{(d, \varphi(m))})^{t} \equiv 1 \pmod{m}$。

与我们没有检测出来的假设矛盾。

故结论得证。

由于质因数分解出来很小,故复杂度我们可以认为是$O(nlog^2n)$,而又因为质数的原根都非常小= =所以...整体来看就是一个常数!

时间: 2024-10-10 06:00:38

求质数的原根的相关文章

C语言求质数的算法

前言 上次被出了一题质数的C语言求解题目(面试),当时用了最粗暴的算法,回来仔细参考资料,其实答案有很多种: 1,小学生版本: 判断 x 是否为质数,就从 2 一直算到 x-1. static rt_uint32_t array1[ARRAY_LEN]; void func1(void) { for (rt_uint32_t i = 1; i <= ARRAY_LEN; i++) { array1[i - 1] = 0; } rt_uint32_t x, y = 0, z = 0; rt_uin

每日一小练——求质数

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:求质数 内容: 试编写一个程序,找出前N个质数.如果没有进一步要求,这不是难题.但在此希望从所知的.使用除法的方法中,用最快的办法来编写程序. 我的解法:上来没多想,打开vs2013就敲了起来,问题果然很简单,分分钟就超神..奥,不对就解决了!这个题目确实很简单,先看看常规解法吧! #include <iostream> #include <math.h> #define endNum 200 using

求质数两个方法的好坏分析(是否易懂,操作次数,运算复杂度时间)

方法1: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <malloc.h> 4 #include <stdbool.h> 5 6 int main() 7 { 8 long i,j,n,ans=0; 9 //vis[x]若为true,则代表质数,若为false,则不是质数 10 bool *vis=(bool *) malloc (sizeof(bool)*100000001); 11 long

求质数方法大总结

最近知乎上看到一道求2000000之内的质数的个数~最近总结了下求质数的方法, 也就顺带总结了下求质数的方法 1.蛮力法求质数 1 public class PrimeTest1 2 { 3 public static boolean isPrime(int numPrime) 4 { 5 for (int i = 2; i < numPrime; i++) 6 { 7 if (numPrime % i == 0) 8 { 9 return false; 10 } 11 } 12 return

求质数数量 - 空间换时间

质数:被自己本身和1整出的数 int getPrimeCount(int value){ int count = 0; int arr[301] = {0};// 0 - is prime , 1 - is not prime int num = (int)sqrt((float)value); for(int i = 2; i <= num ; ++i){ if (!arr[i]){ for(int j = i; i * j < value; ++j){ arr[i * j] = 1; }

求质数的几种算法

1.根据质数的定义求 质数定义:只能被1或者自身整除的自然数(不包括1),称为质数. 利用它的定义可以循环判断该数除以比它小的每个自然数(大于1),如果有能被它整除的,则它就不是质数. 对应代码是: void printPrime(int n){//判断n是否是质数         boolean isPrime=true;//是否是质数的标志         for(int i=n-1;i>1;i—){//n除以每个比n小比1大的自然数 if(n%i==0){//如果有能被整除的,则不是质数

求质数

1.输入被求质数的数 2.输入一行输出质数的个数 3.输入是否继续运算 import java.util.Scanner; public class 质数 { public static void main(String[] args) { boolean isPro = true; while (isPro) { System.out.print("请输入一个数:"); @SuppressWarnings("resource") int num = (new Sc

求质数的方法解析

质数又称素数.指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数.换句话说,只有两个正因数(1和自己)的自然数即为素数.比1大但不是素数的数称为合数.1和0既非素数也非合数.合数是由若干个质数相乘而得到的.所以,质数是合数的基础,没有质数就没有合数. 求素数的方法有很多种,最简单的方法是根据素数的定义来求.对于一个自然数N,用大于1小于N的各个自然数都去除一下N,如果都除不尽,则N为素数,否则N为合数. 但是,如果用素数定义的方法来编制计算机程序,它的效率一定是非常低的,其

[经典算法] Eratosthenes筛选求质数

题目说明: 除了自身之外,无法被其它整数整除的数称之为质数,要求质数很简单,但如何快速的求出质数则一直是程式设计人员与数学家努力的课题,在这边介绍一个著名的 Eratosthenes求质数方法. 题目解析: 首先知道这个问题可以使用回圈来求解,将一个指定的数除以所有小于它的数,若可以整除就不是质数,然而如何减少回圈的检查次数?如何求出小于N的所有质数?首先假设要检查的数是N好了,则事实上只要检查至N的开根号就可以了,道理很简单,假设A*B = N,如果A大于N的开根号,则事实上在小于A之前的检查