TYZ 8/23 原根

来源:互联网 发布:有网络登陆不了微信 编辑:程序博客网 时间:2024/05/16 18:46

题意:



元根

题目描述

 

第一反应:要考数论

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

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

欧拉函数可以在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;elsereturn 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;}


1 0