题意:
元根
:
题目描述
第一反应:要考数论
看完题目之后,这出题人搞了个概念来玩我们的吧
数据范围看完之后,觉得悬
欧拉函数可以在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;
}