ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

原根学习笔记

2020-12-28 21:04:48  阅读:240  来源: 互联网

标签:ch gcd 原根 int 笔记 学习 rg varphi


阶的定义

设 \(m>1\),且 \(gcd(a,m)=1\),那么使得\(a^r\equiv 1(modm)\)成立的最小的正整数\(r\)称为\(a\)对模\(m\)的阶,记为\(\delta m(a)\)

阶的性质

定理一:若 \(m>1\) 并且 \(gcd(a,m)=1\),又满足 \(a^n \equiv 1(modm)\),那么 \(\delta m(a)|n\)

定理二:\(\delta m(a)|\varphi(m)\)

原根

原根的定义

原根,是一个数学符号。设 \(m\) 是正整数,\(a\) 是整数,若 \(a\) 模 \(m\) 的阶等于 \(\varphi(m)\),则称 \(a\)为模 \(m\) 的一个原根。

原根存在的条件

模 \({\displaystyle m}\) 有原根的充要条件是 \(m=2,4,p^k,2p^k\),其中 \(p\) 是奇素数(除了 \(2\) 以外的所有素数),\(k\) 是任意正整数。

原根的判定

若 \(g\) 为模 \(m\) 的原根,则对于任意 \(\varphi(m)\) 的质因子 \(p\),必有 \(g^{\frac{\varphi(m)}{p}}\not\equiv 1 \pmod m\)

求所有的原根

最小原根是不大于 \(\sqrt[4]{m}\) 级别的。

因此,不妨枚举 \([1,\sqrt[4]{m}]\) 的整数,得到最小原根 \(g\)。

再枚举 \(g^s\) 的指数 \(s\),若 \(s\) 与 \(\varphi(m)\) 互质,则 \(g^s\bmod m\) 为一个原根。

由此可知,如果数 \(m\) 存在原根,则原根的个数为 \(\varphi(\varphi(m))\)

代码

洛谷P6091 【模板】原根

#include<cstdio>
#include<cmath>
#include<algorithm>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5;
bool not_pri[maxn];
int n,t,d,pri[maxn],phi[maxn];
void xxs(){
	not_pri[0]=not_pri[1]=1;
	phi[1]=1;
	for(rg int i=2;i<maxn;i++){
		if(!not_pri[i]){
			pri[++pri[0]]=i;
			phi[i]=i-1;
		}
		for(rg int j=1;j<=pri[0] && 1LL*i*pri[j]<maxn;j++){
			not_pri[i*pri[j]]=1;
			if(i%pri[j]==0){
				phi[i*pri[j]]=phi[i]*pri[j];
				break;
			}
			phi[i*pri[j]]=phi[i]*phi[pri[j]];
		}
	}
}
bool jud(rg int now){
	if(now==2 || now==4) return 1;
	if(now%2==0) now/=2;
	for(rg int i=2;pri[i]<=now;i++){
		if(now%pri[i]==0){
			while(now%pri[i]==0){
				now/=pri[i];
			}
			return now==1;
		}
	}
	return 0;
}
int ksm(rg int ds,rg int zs,rg int mod){
	rg int nans=1;
	while(zs){
		if(zs&1) nans=1LL*nans*ds%mod;
		ds=1LL*ds*ds%mod;
		zs>>=1;
	}
	return nans;
}
int sta[maxn],tp,g,ans[maxn],tp2;
void divid(rg int now){
	rg int m=sqrt(now);
	tp=0;
	for(rg int i=2;i<=m;i++){
		if(now%i==0){
			sta[++tp]=i;
			while(now%i==0) now/=i;
		}
	}
	if(now>1) sta[++tp]=now;
}
int gcd(rg int aa,rg int bb){
	return (bb==0)?aa:gcd(bb,aa%bb);
}
bool pd;
int main(){
	xxs();
	t=read();
	while(t--){
		n=read(),d=read();
		if(jud(n)){
			divid(phi[n]);
			for(rg int i=1;;i++){
				pd=1;
				if(gcd(i,n)!=1) continue;
				for(rg int j=1;j<=tp;j++){
					if(ksm(i,phi[n]/sta[j],n)==1){
						pd=0;
						break;
					}
				}
				if(pd){
					g=i;
					break;
				}
			}
			rg int now=1;
			tp2=0;
			for(rg int i=1;tp2<phi[phi[n]];i++){
				now=1LL*now*g%n;
				if(gcd(phi[n],i)==1) ans[++tp2]=now;
			}
			std::sort(ans+1,ans+1+tp2);
			printf("%d\n",phi[phi[n]]);
			for(rg int i=1;i<=phi[phi[n]]/d;i++){
				printf("%d ",ans[i*d]);
			}
			printf("\n");
		} else {
			printf("0\n\n");
		}
	}
	return 0;
}

标签:ch,gcd,原根,int,笔记,学习,rg,varphi
来源: https://www.cnblogs.com/liuchanglc/p/14203590.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有