标签:傻傻 write accept any ring int -o microsoft ons
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 583 Accepted Submission(s): 144
那么来看一下这道题:
首先根据性质1,我们可以通过预处理质数,把不存在的情况判掉。
然后根据性质3,找到一个原根后枚举次方判gcd就可以了。
怎么找到一个原根呢?按照性质2傻傻去跑在这种多组数据的题目里是肯定不行的。
那么有一个喜大普奔的结论来帮助我们:
因为gφ(n)≡1(mod n),而对于比φ(n)小的数都不成立。
枚举φ(n)的质因子p,看gφ(n)/p在模意义下是否是1。
是1的话g就不是原根。
证明起来有点麻烦,这里就不写了。
所以找原根大概是O(n0.25/2)的。
找到之后枚举次方就可以了,因为是充分条件。
想剪个好枝却剪烂的某人在HDU上留下了5个WA... ...
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <cstring> #include <queue> #define LL long long int #define ls (x << 1) #define rs (x << 1 | 1) #define MID int mid=(l+r)>>1 using namespace std; const int N = 1000000+10; int P[N],vis[N],phi[N],tot,n; inline int gcd(int a,int b){return b?gcd(b,a%b):a;} inline void prepare() { phi[1]=1; for(int i=2;i<N;++i){ if(!vis[i])P[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot;++j){ if(i*P[j]>=N)break; vis[i*P[j]]=1; if(i%P[j])phi[i*P[j]]=phi[i]*phi[P[j]]; else{phi[i*P[j]]=phi[i]*P[j];break;} } } } inline int QPow(int d,int z,int Mod) { int ans=1; for(;z;z>>=1,d=1ll*d*d%Mod)if(z&1)ans=1ll*ans*d%Mod; return ans; } inline bool check(int x) { if(x==2 || x==4)return 1; if((x&1)^1)x>>=1; for(int i=2;P[i]<=x;++i) if(x%P[i]==0){ while(x%P[i]==0)x/=P[i]; return x==1?P[i]:0; } return 0; } inline int get_rg(int fx) { int pt[1010],tt=0,Txd=phi[fx]; for(int i=1;P[i]*P[i]<=Txd;++i) if(Txd%P[i]==0){ pt[++tt]=P[i]; while(Txd%P[i]==0)Txd/=P[i]; } if(Txd!=1)pt[++tt]=Txd; for(int i=2;i<=fx;++i) if(QPow(i,phi[fx],fx)==1){ int flag=1; for(int j=1;j<=tt;++j) if(QPow(i,phi[fx]/pt[j],fx)==1){ flag=0;break; } if(flag)return i; } return 0; } inline void work(int fx) { int tt=0,pr[N]; if(fx==2){printf("1\n");return;} if(fx==4){printf("3\n");return;} int T=check(fx); if(!T){printf("-1\n");return;} int g=get_rg(fx); for(int i=1,k=g;i<phi[fx];++i,k=1ll*k*g%fx) if(gcd(i,phi[fx])==1) pr[++tt]=k; sort(pr+1,pr+tt+1); for(int i=1;i<tt;++i) printf("%d ",pr[i]); printf("%d",pr[tt]); printf("\n"); } int main() { prepare(); while(scanf("%d",&n)!=EOF)work(n); return 0; }
标签:傻傻 write accept any ring int -o microsoft ons
原文地址:http://www.cnblogs.com/fenghaoran/p/7110296.html