原根与指标

参考资料

一.阶

1.定义:设\(a,p\)是互质整数,必定有\(x\)满足\(a^x\equiv 1\pmod{p}\),最小的满足条件的正整数\(x\)称为\(a\)\(p\)的阶,记为\(Ord_p(a)\),如果\(\gcd(a,p)!=1\),则不存在阶。
2.性质:
<1>设\(a,p\)是互质整数,存在\(x'\)满足\(a^{x'}\equiv 1\pmod{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\not=\varphi(p)\),是否都满足\(x^d\not\equiv 1\pmod{p}\)
优化:
由于如果\(x^k\equiv 1\pmod{p}\),则\(x^{kd}\equiv 1\pmod{p}\)
\(\varphi(p)=\prod_{i=1}^k p_i^{c_i}\)
只需要对每个\(i\)验证是否满足\(x^{\frac{\varphi(p)}{p_i}}\not\equiv 1\pmod{p}\),因为\(\frac{\varphi(p)}{p_i}\)是除去分解后次幂中含有\(p_i^{c_i}\)以外的所有约数的倍数。这样就相当于判掉了所有\(\varphi(n)\)的约数。

三.指标

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

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

求解\(x^k\equiv a\pmod{p}\),p是质数。
先求出\(p\)的最小原根\(g\),因为p是质数,因此必定存在\(ind_gx\)\(ind_ga\)
所求即变为\(k*ind_gx\equiv ind_ga\pmod{\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\n",ans.size());
	for(int i=0;i<ans.size();i++)printf("%lld\n",ans[i]);
	return 0;
}
posted @ 2019-11-26 10:15  nofind  阅读(685)  评论(0编辑  收藏  举报