原根

文章目录

我搬我自己
借鉴1
借鉴2
借鉴3

定义: ( a , n ) = 1 (a,n)=1 (a,n)=1 使得 a t ≡ 1   ( m o d   n ) a^t\equiv 1\ (mod\ n) at1 (mod n) 的最小的 t t t 成为 a a a 在模 n n n 意义下的阶,记为 o r d n a ord_na ordna
性质: 此时 a φ ( n ) ≡ 1 ( m o d   n ) a^{\varphi(n)}\equiv1(mod\ n) aφ(n)1(mod n) ,于是 o r d n a ∣ φ ( n ) ord_na\mid \varphi(n) ordnaφ(n)

原根

定义:若 o r d n g = φ ( n ) ord_ng=\varphi(n) ordng=φ(n),则 g g g 称为模 n n n 的原根
性质:

  • n = 2 , 4 , p k , 2 ∗ p k n=2,4,p^k,2*p^k n=2,4,pk,2pk p p p 为奇素数) 是有原根 g g g 的充要条件
    有点难证…不会
  • { g 1 , g 2 , . . . , g φ ( n ) } \{g^1,g^2,...,g^{\varphi(n)}\} {g1,g2,...,gφ(n)}是模 n n n 的既约剩余系
    采用反证法证明
    若该集合(有点不严谨)中存在 g i ≡ g j   ( m o d   n )   ( i ! = j ) g^i\equiv g^j\ (mod\ n)\ (i!=j) gigj (mod n) (i!=j)
    则存在 g ∣ i − j ∣ ≡ 1   ( m o d   n ) g^{|i-j|}\equiv1\ (mod\ n) gij1 (mod n) 此时 ∣ i − j ∣ < φ ( n ) |i-j|<\varphi(n) ij<φ(n),矛盾
    所以集合中元素互不相等
    考虑小于 n n n 的和 n n n 互素的 φ ( n ) \varphi(n) φ(n) 个数列组成集合 S S S
    若存在 g i ∉ S g^i\not\in S giS g c d ( g , n ) ≠ 1 gcd(g,n)\not=1 gcd(g,n)=1,显然不成立
    所以集合中的元素和 S S S 中一一对应
    得证
  • 如果模 n n n 有原根,那么它一共有 φ ( φ ( n ) ) \varphi(\varphi(n)) φ(φ(n)) 个原根
    考虑已知一原根 g g g ,有 S = { g 0 , g 1 , . . . , g φ ( n ) − 1 } S=\{g^0,g^1,...,g^{\varphi(n)-1}\} S={g0,g1,...,gφ(n)1}
    设一新原根 q = g t q=g^t q=gt
    只需保证 q k q^k qk n n n 意义下构成集合等于 S S S
    模运算杂结论中证明了 g c d ( t , φ ( n ) ) = 1 gcd(t,\varphi(n))=1 gcd(t,φ(n))=1
    t t t φ ( φ ( n ) ) \varphi(\varphi(n)) φ(φ(n))
    此时有 φ ( φ ( n ) ) \varphi(\varphi(n)) φ(φ(n)) 个原根
    得证

原根:
已知 a φ ( n ) ≡ 1   ( m o d   n ) a^{\varphi(n)}\equiv 1\ (mod\ n) aφ(n)1 (mod n)
满足 g 1 , g 2 , g 3 , . . . , g φ ( n ) g^1,g^2,g^3,...,g^{\varphi(n)} g1,g2,g3,...,gφ(n) n n n 意义下互不相同
求解步骤:

  1. 预处理出 p h i phi phi
  2. 判断哪些 n n n 有原根
  3. 从小到大枚举 g g g 找出对 ∀ p ∣ φ ( n ) \forall p|\varphi(n) pφ(n) 都有 g p ≠ 1 g^p\not=1 gp=1 g g g
  4. 然后找出 ( i , φ ( n ) ) = 1 (i,\varphi(n))=1 (i,φ(n))=1 S = g i S={g^i} S=gi 的原根集合
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
    bool f=0;int x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
    while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return !f?x:-x;
}
#define mp make_pair
const int MAXN=1000000;
const int INF=0x3f3f3f3f;
bool pc[MAXN+5],rt[MAXN+5];
int pcnt,pr[MAXN+5],phi[MAXN+5];
void Init(){
	phi[1]=1;
	for(int i=2;i<=MAXN;i++){
		if(!pc[i]) pr[++pcnt]=i,phi[i]=i-1;
		for(int j=1;j<=pcnt&&i*pr[j]<=MAXN;j++){
			pc[i*pr[j]]=1;
			if(i%pr[j]==0){
				phi[i*pr[j]]=phi[i]*pr[j];
				break;
			}
			phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
	}
	rt[2]=rt[4]=1;
	for(int i=2;i<=pcnt;i++){
		for(int j=1;1ll*j*pr[i]<=MAXN;j*=pr[i])
			rt[j*pr[i]]=1;
		for(int j=2;1ll*j*pr[i]<=MAXN;j*=pr[i])
			rt[j*pr[i]]=1;
	}
	return ;
}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int Pow(int x,int y,int Mod){
	int ret=1;
	while(y){
		if(y&1) ret=1ll*ret*x%Mod;
		x=1ll*x*x%Mod,y>>=1;
	}
	return ret;
}
int fcnt,fac[MAXN+5];
void Split(int n){
	fcnt=0;
	for(int i=2;i*i<=n;i++)
		if(n%i==0){
			fac[++fcnt]=i;
			while(n%i==0)
				n/=i;
		}
	if(n!=1)
		fac[++fcnt]=n;
	return ;
}
vector<int> ans;
int main(){
	Init();
	int T=read();
	while(T--){
		ans.clear();
		int n=read(),d=read();
		if(!rt[n]){
			puts("0\n");
			continue;
		}
		Split(phi[n]);
		int g=0,t=1;
		for(g=1;g<n;g++)
			if(Pow(g,phi[n],n)==1){
				int i=1;
				while(i<=fcnt&&Pow(g,phi[n]/fac[i],n)!=1) i++;
				if(i>fcnt) break;
			}
		for(int i=1;i<=phi[n];i++){
			t=1ll*t*g%n;
			if(gcd(i,phi[n])==1)
				ans.push_back(t);
		}
		sort(ans.begin(),ans.end());
		cout<<phi[phi[n]]<<endl;
		for(int i=d-1;i<phi[phi[n]];i+=d)
			printf("%d ",ans[i]);
		puts("");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值