题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4992
题意:给出n,输出n的所有原根。
思路:求出n的一个原根x,那么对于所以的i,i<phi(n)且(i,phi(n))=1,x^i%n都是n的原根。
int Euler(int n)
{
int i,ans=n;
for(i=2;i*i<=n;i++) if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
int prime[N],tag[N],cnt;
void init()
{
int i,j;
for(i=2;i<N;i++) if(!tag[i])
{
prime[cnt++]=i;
for(j=i+i;j<N;j+=i) tag[j]=1;
}
tag[1]=1;
}
int get(int x)
{
if(x%2==0) return 0;
int i;
for(i=0;i<cnt&&prime[i]*prime[i]<=x;i++) if(x%prime[i]==0)
{
while(x%prime[i]==0) x/=prime[i];
if(x!=1) return 0;
return prime[i];
}
return x;
}
int n;
int myPow(i64 x,i64 y)
{
i64 ans=1;
while(y)
{
if(y&1) ans=ans*x%n;
x=x*x%n;
y>>=1;
}
return (int)ans;
}
int ee;
vector<int> V;
int ok(int t)
{
if(myPow(t,ee)!=1) return 0;
int i;
FOR0(i,SZ(V)) if(myPow(t,V[i])==1) return 0;
return 1;
}
int Gcd(int x,int y)
{
if(y==0) return x;
return Gcd(y,x%y);
}
int main()
{
init();
while(scanf("%d",&n)!=-1)
{
if(n==2)
{
puts("1");
continue;
}
if(n==4)
{
puts("3");
continue;
}
int t=n%2==0?get(n/2):get(n);
if(!t)
{
puts("-1");
continue;
}
ee=Euler(n);
V.clear();
int i;
for(i=2;i*i<=ee;i++) if(ee%i==0)
{
V.pb(i);
if(i*i!=ee) V.pb(ee/i);
}
for(i=2;i<n;i++) if(ok(i)) break;
int Min=i;
vector<int> ans;
for(i=1;i<ee;i++)
{
if(Gcd(i,ee)!=1) continue;
ans.pb(myPow(Min,i));
}
sort(all(ans));
for(i=0;i<SZ(ans);i++)
{
if(i) putchar(' ');
printf("%d",ans[i]);
}
puts("");
}
}