阶,原根,指标和N次剩余

阶,原根,指标和 N N N次剩余

参考博客

阶的定义

a a a, p p p是互质整数,存在 x x x满足 a x ≡ 1 m o d    p a^x\equiv 1\mod p ax1modp,最小的满足条件的正整数 x x x称为 a a a p p p的阶,记为 O r d p ( a ) Ord_p(a) Ordp(a)

性质

性质一

a a a, p p p是互质整数,存在 x ′ x' x满足 a x ′ ≡ 1 m o d    p a^{x'}\equiv 1\mod p ax1modp,则 O r d p ( a ) ∣ x ′ Ord_p(a)|x' Ordp(a)x

证明

反证法

a a a, p p p是互质整数,存在整数 x ′ x' x满足 a x ′ ≡ 1 m o d    p a^{x'}\equiv 1\mod p ax1modp O r d p ( a ) ∤ x ′ Ord_p(a)\not|x' Ordp(a)x

x ≡ x ′ m o d    O r d p ( a ) x\equiv x'\mod Ord_p(a) xxmodOrdp(a) 1 ≤ x < O r d p ( a ) 1\leq x< Ord_p(a) 1x<Ordp(a)

显然 a x ≡ 1 m o d    p a^{x}\equiv 1\mod p ax1modp,与 O r d Ord Ord的定义矛盾

性质二

a a a, p p p是互质整数, O r d p ( a ) ∣ φ ( p ) Ord_p(a)|\varphi(p) Ordp(a)φ(p)

证明

a φ ( p ) ≡ 1 m o d    p a^{\varphi(p)}\equiv 1\mod p aφ(p)1modp

原根

原根的定义

a a a, p p p是互质整数, O r d p ( a ) = φ ( p ) Ord_p(a)=\varphi(p) Ordp(a)=φ(p),则称 a a a是模 p p p的一个原根

性质

性质一

只有 2 , 4 , p k , 2 p k 2,4,p^k,2p^k 2,4,pk,2pk有原根( p p p为奇素数)

性质二

一个数 p p p若存在原根,则有 φ ( φ ( p ) ) \varphi(\varphi(p)) φ(φ(p))个原根

证明

假设已经找到了一个原根 g g g,那么对于所有 gcd ⁡ ( x , φ ( p ) ) = 1 \gcd(x,\varphi(p))=1 gcd(x,φ(p))=1 x x x, g x g^x gx也是 p p p的原根

性质三

a a a p p p的原根, a 0 , a 1 . . . a φ ( p ) − 1 a^0,a^1...a^{\varphi(p)-1} a0,a1...aφ(p)1两两不同,即构成了模 p p p的简化剩余系

如何求原根

先求最小正原根

从小到大枚举 g g g并检验 g g g是否是 p p p的原根,枚举次数是 p 0.25 p^{0.25} p0.25级别的

如何检验?

满足 ∀ i < v a r p h i ( p ) \forall i<varphi(p) i<varphi(p), g i ≠ 1 m o d    p g^i\not=1\mod p gi=1modp,且 g φ ( p ) ≡ 1 m o d    p g^{\varphi(p)}\equiv 1\mod p gφ(p)1modp

根据阶的性质,只需要检验 φ ( p ) \varphi(p) φ(p)的所有真因数即可,考虑检验所有真因数的倍数

φ ( p ) = ∏ i q i c i \varphi(p)=\prod_iq_i^{c_i} φ(p)=iqici

∀ i \forall i i,检验 φ ( p ) q i \frac{\varphi(p)}{q_i} qiφ(p)即可

指标

定义

g g g p p p的原根, a a a, p p p是互质整数,存在唯一的整数 x x x满足 g x ≡ a m o d    p g^x\equiv a\mod p gxamodp,称 x x x为以 g g g为底对模 p p p的一个指标,记为 x = i n d g a x=ind_ga x=indga

性质

性质一

a ≡ b m o d    p a\equiv b\mod p abmodp,则 i n d g a ≡ i n d g b m o d    φ ( p ) ind_ga\equiv ind_gb\mod \varphi(p) indgaindgbmodφ(p)

性质二

i n d g ( a b ) ≡ i n d g ( a ) + i n d g ( b ) m o d    φ ( p ) ind_g(ab)\equiv ind_g(a)+ind_g(b)\mod \varphi(p) indg(ab)indg(a)+indg(b)modφ(p)

性质三

i n d g ( a k ) ≡ k × i n d g ( a ) m o d    φ ( p ) ind_g(a^k)\equiv k\times ind_g(a)\mod \varphi(p) indg(ak)k×indg(a)modφ(p)

如何求指标

就是求离散对数,直接 B S G S BSGS BSGS

BSGS

x x x满足 A x ≡ B m o d    p A^x\equiv B\mod p AxBmodp,满足 gcd ⁡ ( A , p ) = 1 \gcd(A,p)=1 gcd(A,p)=1

显然 x ∈ [ 0 , p ) x\in [0,p) x[0,p)

M = ⌈ ( p ) ⌉ M=\lceil \sqrt(p)\rceil M=( p)

x = i × M − c , c ∈ [ 0 , M ) x=i\times M-c,c\in [0,M) x=i×Mc,c[0,M)

A i × M − c ≡ B m o d    p A^{i\times M-c}\equiv B\mod p Ai×McBmodp
A i × M ≡ B × A c m o d    p A^ {i\times M}\equiv B\times A^c\mod p Ai×MB×Acmodp
枚举 c c c,把 B × A c B\times A^c B×Ac插进一个map,最后枚举 i i i求解即可

N N N次剩余

求所有 x x x满足 x A ≡ B m o d    C x^A\equiv B\mod C xABmodC

分解问题

考虑将 C C C质因数分解

子问题为求所有 x x x满足 x A ≡ B m o d    p i α i x^A\equiv B\mod p_i^{\alpha_i} xABmodpiαi

每个方程可能有多种解,每个方程中选一个解,这样每组选择方法唯一对应一种答案,用 E x C r t / C r t ExCrt/Crt ExCrt/Crt合并即可

处理每个 x A ≡ B m o d    p α x^A\equiv B\mod p^\alpha xABmodpα

gcd ⁡ ( B , p α ) = 1 \gcd(B,p^\alpha)=1 gcd(B,pα)=1

M = p α M=p^\alpha M=pα, g g g M M M的原根, y = i n d M x , z = i n d M B y=ind_Mx,z=ind_MB y=indMx,z=indMB
A × y ≡ z m o d    φ ( M ) A\times y\equiv z\mod \varphi(M) A×yzmodφ(M)
z ≡ 0 m o d    φ ( M ) z\equiv 0\mod \varphi(M) z0modφ(M)
,设 q w q = gcd ⁡ ( A , φ ( M ) ) qwq=\gcd(A,\varphi(M)) qwq=gcd(A,φ(M))

y ≡ 0 m o d    φ ( M ) q w q y\equiv 0\mod \frac{\varphi(M)}{qwq} y0modqwqφ(M)
y ∈ [ 0 , φ ( M ) ) y\in [0,\varphi(M)) y[0,φ(M)),共有 q w q qwq qwq组解

否则,设 q w q = gcd ⁡ ( A , z , φ ( M ) ) qwq=\gcd(A,z,\varphi(M)) qwq=gcd(A,z,φ(M))
y ≡ z q w q × ( A q w q ) − 1 m o d    φ ( M ) q w q y\equiv \frac{z}{qwq}\times (\frac{A}{qwq})^{-1}\mod\frac{\varphi(M)}{qwq} yqwqz×(qwqA)1modqwqφ(M)
x ≡ g y m o d    M x\equiv g^y\mod M xgymodM
y ∈ [ 0 , φ ( M ) ) y\in [0,\varphi(M)) y[0,φ(M)),有 q w q qwq qwq组解

gcd ⁡ ( B , p α ) = p q ( 1 ≤ q < α ) \gcd(B,p^\alpha)=p^q(1\leq q<\alpha) gcd(B,pα)=pq(1q<α)

x A ≡ B m o d    p α x^A\equiv B\mod p^\alpha xABmodpα

B = z × p q B=z\times p^q B=z×pq, x = y × p a x=y\times p^a x=y×pa

( y × p a ) A ≡ z × p q m o d    p α (y\times p^a)^A\equiv z\times p^q\mod p^\alpha (y×pa)Az×pqmodpα
y A × p a A ≡ z × p q m o d    p α y^A\times p^{aA}\equiv z\times p^q\mod p^\alpha yA×paAz×pqmodpα
显然, A ∣ q A|q Aq,反之无解

求解 y A ≡ z m o d    p α − q y^A\equiv z\mod p^{\alpha-q} yAzmodpαq, x = y × p q A x=y\times p^\frac{q}{A} x=y×pAq即可

每组 y A ≡ z m o d    p α − q A y^A\equiv z\mod p^{\alpha-\frac{q}{A}} yAzmodpαAq的解唯一对应一组 x A ≡ B m o d    p α x^A\equiv B\mod p^{\alpha} xABmodpα的解

所以每个 y y y分别对应 p q − q A p^{q-\frac{q}{A}} pqAq x x x

B ≡ 0 m o d    p α B\equiv 0\mod p^\alpha B0modpα

x ≡ 0 m o d    p ⌈ α A ⌉ x\equiv 0\mod p^{\lceil\frac{\alpha}{A}\rceil} x0modpAα

x ∈ [ 0 , p α ) x\in [0,p^\alpha) x[0,pα),共有 p α − ⌈ α A ⌉ p^{\alpha-\lceil\frac{\alpha}{A}\rceil} pαAα组解

p p p 2 2 2

x A ≡ B m o d    2 α x^A\equiv B\mod 2^{\alpha} xABmod2α

求出 y A ≡ B m o d    2 α − 1 y^A\equiv B \mod 2^{\alpha-1} yABmod2α1, x = y x=y x=y x = y + 2 α − 1 x=y+2^{\alpha-1} x=y+2α1

如何用 E x C r t ExCrt ExCrt合并答案?

以上选出的答案都为同余方程的形式,考虑如何合并两个同余方程

{ x ≡ c 1 m o d    p 1 x ≡ c 2 m o d    p 2 \left\{\begin{aligned}x\equiv c_1\mod p_1\\x\equiv c_2\mod p_2\end{aligned}\right. {xc1modp1xc2modp2
c 1 + p 1 × k 1 = c 2 + p 2 × k 2 c_1+p_1\times k_1=c_2+p_2\times k_2 c1+p1×k1=c2+p2×k2
p 1 × k 1 − p 2 × k 2 ≡ c 2 − c 1 p_1\times k_1-p_2\times k_2\equiv c_2-c_1 p1×k1p2×k2c2c1
q w q = gcd ⁡ ( p 1 , p 2 ) qwq=\gcd(p_1,p_2) qwq=gcd(p1,p2),若 q w q ∤ ( c 2 − c 1 ) qwq\not|(c_2-c_1) qwq(c2c1),无解

否则,令 P 1 = p 1 q w q , P 2 = p 2 q w q , C = c 2 − c 1 q w q P_1=\frac{p_1}{qwq},P_2=\frac{p_2}{qwq},C=\frac{c_2-c_1}{qwq} P1=qwqp1,P2=qwqp2,C=qwqc2c1

k 1 k_1 k1, k 1 ≡ C P 1 m o d    P 2 k_1\equiv\frac{C}{P_1}\mod P_2 k1P1CmodP2

x 0 = c 1 + k 1 × p 1 x_0=c_1+k_1\times p_1 x0=c1+k1×p1
= c 1 + ( k 1 + p 2 q w q k 2 ) × p 1 =c_1+(k_1+\frac{p_2}{qwq}k_2)\times p_1 =c1+(k1+qwqp2k2)×p1
x ≡ k 1 × p 1 + c 1 m o d    p 1 p 2 gcd ⁡ ( p 1 , p 2 ) x\equiv k_1\times p_1+c_1\mod \frac{p_1p_2}{\gcd(p_1,p_2)} xk1×p1+c1modgcd(p1,p2)p1p2

代码

#include<bits/stdc++.h>
using namespace std;
#define Ri register
template<typename T>inline T read(Ri T& t)
{Ri T f=1;Ri char ch=getchar();t=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9')t=t*10+ch-'0',ch=getchar();t*=f;return t;}
template <typename T,typename...Args>
inline void read(T&t,Args&...args)
{read(t);read(args...);}
#define ll long long
inline ll power(Ri ll x,Ri ll k,Ri ll p=1e18)
{
	ll re=1;
	for(;k;k>>=1,x=x*x%p)if(k&1)re=re*x%p;
	return re; 
}
inline int BSGS(ll b,ll n,ll p)//B^i=n/mod p
{
	if(n==1)return 0;
	map<int,int> mp;
	int m=ceil(sqrt(p))+1;
	ll t=n;
	for(int i=0;i<=m;i++,t=t*b%p)mp[t]=i;
	t=power(b,m,p);
	for(ll i=1,s=t;i<=m;i++,s=s*t%p)
		if(mp.count(s))
			return i*m-mp[s];
}
inline ll gcd(ll a,ll b)
{
	if(b==0)return a;
	return gcd(b,a%b); 
}
int pri[1000005],pri_top;
bool check(int n,int g,int varphi)
{
	if(power(g,varphi,n)!=1)return 0;
	for(int i=1;i<=pri_top;i++)
		if(power(g,varphi/pri[i],n)==1)
			return 0;
	return 1;
}
int get_g(int n,int varphi)
{
	int phi=varphi;
	pri_top=0;
	for(int i=2;i*i<=phi;i++)
	{
		if(phi%i)continue;
		pri[++pri_top]=i;
		while(phi%i==0)phi/=i;
	}
	if(phi!=1)pri[++pri_top]=phi;
//		printf("varphi=%d,phi:",varphi[n]);for(int i=1;i<=pri_top;i++)printf("%d ",pri[i]);printf("\n");
	int g=1;while(check(n,g,varphi)==0)g++;
	return g;
}
#define Pii pair<int,int>
#define Vii vector<pair<int,int> >
int Exgcd(int a,int b,ll & x,ll & y)
{
	if(b==0)return x=1,y=0,a;
	int re=Exgcd(b,a%b,x,y);
	ll qwq=x;
	x=y;y=qwq-(a/b)*y;
	return re;
}
int Inv(int a,int p)
{
	ll x,y;
	Exgcd(a,p,x,y);
	return (x%p+p)%p;
}
Vii SOLVE(int A,int B,int P,int Alpha)//x^A=B mod P^Alpha
{
	int M=power(P,Alpha);B%=M;	
//	printf("SOLVE:x^%d=%d mod %d^%d\n",A,B,P,Alpha);
	if(P==2)
	{
		if(Alpha==0)return {make_pair(0,1)};
		Vii pre=SOLVE(A,B,2,Alpha-1);
		Vii re;
		for(auto i:pre)
		{
			ll qwq=i.first;
			if(power(qwq,A,M)==B)re.push_back(make_pair(qwq,M));
			qwq=(qwq+M/2)%M;
			if(power(qwq,A,M)==B)re.push_back(make_pair(qwq,M));
		}
		return re;
	}
	Vii re;int var_M=M/P*(P-1);
	if(B==0)
	{
		int qwq=power(P,ceil((double)Alpha/A));
		for(int i=0;i*qwq<M;i++)
			re.push_back(make_pair(i*qwq,M));
		return re;
	}

	if(gcd(B,M)==1)
	{
		int g=get_g(M,var_M);
//		printf("g=%d var_M=%d\n",g,var_M);
		int z=BSGS(g,B,M);
		if(z==0)
		{
			int qwq=gcd(A,var_M);
			for(int i=0;i<var_M;i+=var_M/qwq)
				re.push_back(make_pair(power(g,i,M),M));
			return re; 
		}
		int qwq=gcd(A,gcd(z,var_M));
//		printf("%d^%d=%d mod %d\n",g,z,B,M);
		if(gcd(A/qwq,var_M/qwq)!=1)return {};
		int y=(ll)z/qwq*Inv(A/qwq,var_M/qwq)%(var_M/qwq);
		for(int i=0;i<qwq;i++)
//			printf("%d^%d\n",g,y+var_M/qwq*i),
			re.push_back(make_pair(power(g,y+var_M/qwq*i,M),M));
	}
	else
	{
		int gc=gcd(B,M);
		int q=1,qaq=P;
		while(qaq!=gc)
			qaq=qaq*P,q++;
		if(q%A)return {};
		int z=B/qaq;
		Vii pre=SOLVE(A,z,P,Alpha-q);
		int qwq=power(P,q/A,M);
		int qAq=power(P,q-q/A);
		int QaQ=power(P,Alpha-q);
		for(auto i:pre)
			for(ll j=0;j<qAq;j++)
				re.push_back(make_pair((i.first+j*QaQ%M)*qwq%M,M));
	}
//	printf("SOLVE:x^%d=%d mod %d^%d\n",A,B,P,Alpha);
//	for(auto i:re)printf("%lld mod %lld\n",i.first,i.second);
	return re;
}
Vii solution[1005];
int solution_top;
vector<long long> ans;
bool without_ans;
void DFS(int now,ll m,ll p)
{
	if(without_ans)return;
	if(now>solution_top)return ans.push_back(m),void();
	for(auto i:solution[now])
	{
		ll qwq=gcd(p,i.second);
		ll C=(i.first-m%i.second+i.second)%i.second;
		if(C%qwq)return without_ans=1,ans={},void();
		ll P1=p/qwq,P2=i.second/qwq,c=C/qwq;
		ll k1=c*Inv(P1,P2)%P2;
		ll p2=p*i.second/gcd(p,i.second);
		DFS(now+1,(k1*p+m)%p2,p2);
	}
}
void solve(int A,int B,int C)//x^A=b mod C
{	
	int M=C;solution_top=0;
	for(int i=2;i*i<=M;i++)
		if(M%i==0)
		{
			int sum=0;
			while(M%i==0)
				M/=i,sum++;
			solution[++solution_top]=SOLVE(A,B,i,sum);
//			printf("Devided Question:x^%d=%d mod %d^%d\n",A,B,i,sum);
//			for(auto i:solution[solution_top])printf("%lld mod %lld\n",i.first,i.second);
		}
	if(M!=1)solution[++solution_top]=SOLVE(A,B,M,1);
//	printf("Devided Question:x^%d=%d mod %d^%d\n",A,B,M,1);
//	for(auto i:solution[solution_top])printf("%lld mod %lld\n",i.first,i.second);
	ans.clear();	
	without_ans=0;
	DFS(1,0,1);
	sort(ans.begin(),ans.end());
	printf("%d\n",ans.size());
	if(ans.size()==0)return;
	for(auto i:ans)printf("%lld ",i);
	printf("\n");
}
int main()
{
	int T;
	read(T);
	while(T--)
	{
		int A,B,C;
		read(A,C,B);
		solve(A,B,C);
	}
	return 0
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值