阶
定义:
(
a
,
n
)
=
1
(a,n)=1
(a,n)=1 使得
a
t
≡
1
(
m
o
d
n
)
a^t\equiv 1\ (mod\ n)
at≡1 (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,2∗pk(
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) gi≡gj (mod n) (i!=j)
则存在 g ∣ i − j ∣ ≡ 1 ( m o d n ) g^{|i-j|}\equiv1\ (mod\ n) g∣i−j∣≡1 (mod n) 此时 ∣ i − j ∣ < φ ( n ) |i-j|<\varphi(n) ∣i−j∣<φ(n),矛盾
所以集合中元素互不相等
考虑小于 n n n 的和 n n n 互素的 φ ( n ) \varphi(n) φ(n) 个数列组成集合 S S S
若存在 g i ∉ S g^i\not\in S gi∈S 则 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 意义下互不相同
求解步骤:
- 预处理出 p h i phi phi
- 判断哪些 n n n 有原根
- 从小到大枚举 g g g 找出对 ∀ p ∣ φ ( n ) \forall p|\varphi(n) ∀p∣φ(n) 都有 g p ≠ 1 g^p\not=1 gp=1 的 g g g
- 然后找出 ( 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;
}