hdu 4992 Primitive Roots 求原根模板
Posted wy_2016
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4992 Primitive Roots 求原根模板相关的知识,希望对你有一定的参考价值。
大题流程: 判定是否有原根->求出最小原根->利用最小原根找出全部原根
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e6+5; int prime[maxn+5]; bool check[maxn+5]; int phi[maxn+5]; int num_prime; void init() { memset(check, false, sizeof(check)); phi[1]=1; for(int i=2; i<=maxn; i++) { if(!check[i]) { prime[num_prime++]=i; phi[i]=i-1; } for(int j=0; j<num_prime; j++) { if(i*prime[j]>maxn) break; check[i*prime[j]]=true; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else { phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } } LL gcd(LL a, LL b) { return b? gcd(b,a%b):a; } void get(LL n,vector<LL>& fac) //对n进行因式分解 { fac.clear(); for(LL i=2; i*i<=n; i++) if(n%i==0) { fac.push_back(i); while(n%i==0) n/=i; } if(n>1) fac.push_back(n); } LL qpow(LL x,LL n,LL mod) //求x^n%mod { LL ret=1; for(; n; n>>=1) { if(n&1) ret=ret*x%mod; x=x*x%mod; } return ret; } vector<LL> fac; vector<LL> ans; bool ok(LL x) { if(x%2==0) x/=2; if(x%2==0) return false; for(int i=0; prime[i]*prime[i]<=x; i++) if(x%prime[i]==0) { while(x%prime[i]==0) x/=prime[i]; return x==1; } return true; } LL get_g(LL p) //得到一个正整数p的最小原根 { for(int i=2; i<p; i++) { bool flag=false; for(LL x:fac) if(qpow(i,phi[p]/x,p)==1) { flag=true; break; } if(!flag&&qpow(i,phi[p],p)==1) return i; } } void GetAns(LL g,LL p,vector<LL>& ans) //由最小原根p,得到某正整数p的全部原根 { ans.clear(); ans.push_back(g); for(int i=2; i<phi[p]; i++) if(gcd(i,phi[p])==1) ans.push_back(qpow(g,i,p)); } int main() { init(); LL p; while(~scanf("%lld",&p)) { if(p==2||p==4) { printf("%lld\n",p-1); continue; } if(!ok(p)) //首先判断是否有原根 { puts("-1"); continue; } get(phi[p],fac); LL g=get_g(p); //定义g为最小原根 GetAns(g,p,ans); sort(ans.begin(),ans.end()); for(int i=0; i<ans.size(); i++) printf("%lld%c",ans[i],i==ans.size()-1? ‘\n‘:‘ ‘); } }
以上是关于hdu 4992 Primitive Roots 求原根模板的主要内容,如果未能解决你的问题,请参考以下文章