51nod1135[原根]

转载地址:https://www.cnblogs.com/geloutingyu/p/6219868.html

思路:设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)给出1个质数P,找出P最小的原根。

我们先了解一下阶的概念:满足 a^r Ξ (1 mod m) ---1 的最小 r 即为 a%m的阶,我们可以直接从小到大枚举a, 然后将 r= φ(m) 带入进去,

判断如果满足  1式(即 a^x%m=1当且仅当 x=r 时成立)的话即为我们所求的答案。又因为输入的 m为质数,所以 r= φ(m)=m-1. 

判断对于当前 a,x=m-1 是否是 a^x%m=1---2 成立的唯一解我们不可能直接从正面枚举每个x,因为我们并不知道是否存在一个数 n, x>n时2式一定不成立,也就是我们不能确定枚举 x 的范围,那么枚举 x 也就无从谈起咯。不过还有有这样一个定理 对 (m-1) 只因分解成 m1, m2, m3....mk,若存在 x=(m-1)/mi 使得式2成立,那么

当前 a 不是 a mod m 的原根。所以我们就可以从反面枚举 x 啦,若当前 a 使得 x=(m-1)/mi (1<=i<=k)对于式2都不满足, 那么当前 a 即为所求解啦~

#include<cstdio>
#define maxl 100010

int p[maxl];
long long pri,t,ans;

inline long long qp(long long a,long long b)
{
	long long ans=1,cnt=a;
	while(b)
	{
		if(b&1)
			ans=(ans*cnt)%pri;
		cnt=(cnt*cnt)%pri;
		b>>=1;
	}
	return ans;
}

inline void prework()
{
	t=pri-1;
	for(int i=2;i*i<=t;i++)
	if(t%i==0)
	{
		p[++p[0]]=i;
		while(t%i==9)
			t/=i;
	}
	if(t!=1) 
		p[++p[0]]=t;
}

inline void mainwork()
{
	bool flag;ans=0;
	for(int x=2;x<=pri && !ans;x++)
	{
		flag=true;
		for(int j=1;j<=p[0] && flag;j++)
		{
			t=qp(x,(pri-1)/p[j]);
			if(t==1)
				flag=false;
		}
		if(flag)
			ans=x;
	}
}

inline void print()
{
	printf("%d\n",ans);
}


int main()
{
	while(~scanf("%lld",&pri))
	{
		prework();
		mainwork();
		print();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值