原根与指标

参考资料

一.阶

1.定义:设(a,p)是互质整数,必定有(x)满足(a^xequiv 1pmod{p}),最小的满足条件的正整数(x)称为(a)(p)的阶,记为(Ord_p(a)),如果(gcd(a,p)!=1),则不存在阶。
2.性质:
<1>设(a,p)是互质整数,存在(x')满足(a^{x'}equiv 1pmod{p}),则(Ord_p(a)|x')
<2>设(a,p)是互质整数,有(Ord_p(a)|varphi(p))(根据欧拉定理反证)。

二.原根

1.定义:设(a,p)为互质整数,若(Ord_p(a)=varphi(p)),则称(a)是模(p)的一个原根。
2.性质:
<1>只有(2,4,p^k,2*p^k)(p)是奇素数)有原根。
<2>一个数(p)若存在原根,则它有(varphi(varphi(p)))个原根。
<3>(a)(p)的原根,(a^0,a^1,a^2...a^{Ord_p(a)-1})(p)两两不同。即当(a)(p)的原根时,(a^0,a^1,a^2...a^{Ord_p(a)-1})构成了模(p)的简化剩余系。
3.求一个数的原根:
暴力:
(2)开始暴力枚举(x),要求(gcd(x,p)=1),之后检验(x)是否为(p)的原根。
由于(Ord_P(x)|varphi(p)),我们需要检验对于任意(d|varphi(p))(d ot=varphi(p)),是否都满足(x^d otequiv 1pmod{p})
优化:
由于如果(x^kequiv 1pmod{p}),则(x^{kd}equiv 1pmod{p})
(varphi(p)=prod_{i=1}^k p_i^{c_i})
只需要对每个(i)验证是否满足(x^{frac{varphi(p)}{p_i}} otequiv 1pmod{p}),因为(frac{varphi(p)}{p_i})是除去分解后次幂中含有(p_i^{c_i})以外的所有约数的倍数。这样就相当于判掉了所有(varphi(n))的约数。

三.指标

1.定义:设(g)是模(p)的一个原根,整数(a)(p)互质,则存在唯一的整数(x)满足:(g^xequiv apmod{p}),称(x)为以(g)为底对模(p)的一个指标。记为(x=ind_ga)
2.性质:
<1>(aequiv bpmod{p}->ind_gaequiv ind_gbpmod{varphi(p))})
<2>(ind_g(ab)equiv ind_ga+ind_gbpmod{varphi(p)})
<3>(ind_g(a^k)equiv k*ind_gapmod{varphi(p)})
3.求指标:直接(BSGS)即可。

四.N次剩余问题(转自)

求解(x^kequiv apmod{p}),p是质数。
先求出(p)的最小原根(g),因为p是质数,因此必定存在(ind_gx)(ind_ga)
所求即变为(k*ind_gxequiv ind_gapmod{varphi(p)})
(exgcd)解出即可。
模板题
code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a,K,mod,g,t,x,y,d;
vector<int>prime,ans;
inline int power(int x,int k,int mod)
{
	int res=1;
	while(k)
	{
		if(k&1)res=res*x%mod;
		x=x*x%mod;k>>=1;
	}
	return res;
}
inline int find(int p)
{
	int tmp=p-1;
	for(int i=2;i*i<=tmp;i++)
	{
		if(tmp%i)continue;
		prime.push_back(i);
		while(tmp%i==0)tmp/=i;
	}
	if(tmp>1)prime.push_back(tmp);
	for(int g=1;g<=p;g++)
	{
		bool flag=1;
		for(unsigned int i=0;i<prime.size();i++)
			if(power(g,(p-1)/prime[i],p)==1){flag=0;break;}
		if(flag)return g;
	}
	return -1;
}
inline int BSGS(int a,int b,int mod)
{
	if(b==1)return 0;
	if(!a)return !b?1:-1;
    map<int,int>mp;mp.clear();
    int t=ceil(sqrt(mod));
    for(int i=0,j=1;i<=t;i++,j=j*a%mod)mp[b*j%mod]=i;
    a=power(a,t,mod);
    for(int i=1,j=a;i<=t;i++,j=j*a%mod)if(mp.count(j))return i*t-mp[j];
	return -1;
}
int exgcd(int a,int b,int &x,int &y)
{
	if(!b){x=1,y=0;return a;}
	int d=exgcd(b,a%b,x,y);
	int z=x;x=y,y=z-(a/b)*y;
	return d;
}
signed main()
{
	scanf("%lld%lld%lld",&mod,&K,&a);
	if(!a){puts("1");puts("0");return 0;}
	g=find(mod);t=BSGS(g,a,mod);
	//cerr<<"test::"<<g<<' '<<t<<endl;
	d=exgcd(K,mod-1,x,y);
	if(t%d){puts("0");return 0;}
	int P=(mod-1)/d;
	x=(x*(t/d)%P+P)%P;
	while(x<mod)
	{
		ans.push_back(power(g,x,mod));
		x+=P;
	}
	sort(ans.begin(),ans.end());
	printf("%lld
",ans.size());
	for(int i=0;i<ans.size();i++)printf("%lld
",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/nofind/p/11933586.html