TYZ 8/23 原根

原根算法解析与实现
博客探讨了原根的概念,以及在NOIP竞赛中可能遇到的算法问题。作者指出,面对数论题目,数据范围较大,需要使用欧拉函数和快速幂等技术。文章详细解释了如何计算欧拉函数,并给出O(n)复杂度的实现。同时提醒读者,对于1的元根情况需特殊处理,避免输出错误。

题意:



元根

题目描述

 

第一反应:要考数论

看完题目之后,这出题人搞了个概念来玩我们的吧

数据范围看完之后,觉得悬

欧拉函数可以在n^0.5内算完,互质的数也一样,

Int 欧拉函数=m

算出来之后,假设有M个的话,那么枚举a需要m,每个a的阶数最坏也是m,

快速幂看来少不了了

所以最坏是m^2

这样看来,eular函数各种风骚求法就不用了,老老实实地敲了个o(n)的欧拉函数带分解

M究竟有多少个呢,虽然phi(10000)(10000的欧拉函数)=4000,但是之前的欧拉函数的规模有接近10000的,所以m^2的复杂度,再加上优化

代码如下:

 大家注意啊,1的元根就是1,这个会输出-1,请大家特殊判断

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int n;
typedef long long ll;
const int maxn=10005;
vector<int> eular;
bool used[maxn];
int gcd(int a,int b)
{
	if(!b)
	return a;
	else
	return gcd(b,a%b);
}
void geteular(int n)
{
	eular.push_back(1);
	for(int i=2;i<n;i++)
	{
		if(used[i])
		continue;
		int nw=gcd(i,n);
		if(nw==1)
		{
			eular.push_back(i);
		}
		else
		{
			used[i]=1;
			for(int j=2;;j++)
			{
				if(i*j>n)
				break;
				int po=i*j;
				used[po]=1;
			}
		}
	}
 } 
 int mod_pow(int Base,int Exp,int Mod)
 {
 	ll x=Base,n=Exp,MOD=Mod;
 	ll res=1;
 	while(n>0)
 	{
 		if(n&1)
 		res=res*x%MOD;
 		x=x*x%MOD;
 		n>>=1;
	 }
	 int RES=res;
	 return RES;
 }
 int m;
 bool fuyi;
int main()
{
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	cin>>m;
	geteular(m);
	int phi=eular.size();
	for(int i=0;i<phi;i++)
	{
		int nw=eular[i];
		int Re=mod_pow(nw,phi,m);
		if(Re!=1)
		continue;
	    for(int d=1;d<=phi;d++)
	    {
	    	if(phi%d)
	    	continue;
	    	int Result=mod_pow(nw,d,m);
	    	if(Result==1)
	    	{
	    		if(d==phi)
	    		{
	    			printf("%d\n",nw);
	    			fuyi=1;
				}
				break;
			}
		}
	}
	if(!fuyi)
	cout<<-1<<endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值