1. 程式人生 > >HDU 4992 Primitive Roots (求原根)

HDU 4992 Primitive Roots (求原根)

Primitive Roots

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 949    Accepted Submission(s): 239


Problem Description We say that integer x, 0 < x < n, is a primitive root modulo n if and only if the minimum positive integer y which makes xy = 1 (mod n) true is φ(n) .Here φ(n) is an arithmetic function that counts the totatives of n, that is, the positive integers less than or equal to n that are relatively prime to n. Write a program which given any positive integer n( 2 <= n < 1000000) outputs all primitive roots of n in ascending order.
Input Multi test cases.
Each line of the input contains a positive integer n. Input is terminated by the end-of-file seperator.
Output For each n, outputs all primitive roots of n in ascending order in a single line, if there is no primitive root for n just print -1 in a single line.
Sample Input 4 25
Sample Output 3 2 3 8 12 13 17 22 23
Source 題意:求出 n的所有原根 分析: 利用原根的定義還是很好解決的,至於定義和定理可以看一下ACdream的部落格  
傳送門
AC程式碼:
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>v;
const int maxn=1e6+10;
int zs[maxn];  //質數表 
int ans[maxn];
bool vj(int n)  //判斷 是否滿足 p^a||2*p^a &&p是奇質數 
{
	if(n%2==0)
	n>>=1;
	if(!zs[n])
	return 1; 
	for(int i=3;i*i<=n;i+=2)
	{
		if(n%i==0)
		{
			while(n%i==0) n/=i;
			return n==1; 
		}
	}
	return 0;
} 
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
int quick_mod(int aa,int b,int mod)
{
	long long c=1;
	long long a=aa;
	while(b)
	{
		if(b&1)
		{
			c*=a;
			c%=mod;
		}
		a*=a;
		a%=mod;
		b>>=1;	
	}
	return (int) c;
} 
int euler(int n)
{
	int anss=n,t=n;
	for(int i=2;i*i<=n;i++)
	{
		if(t%i==0)
		{
			anss=anss/i*(i-1);
			while(t%i==0) t/=i;
		}
	}
	if(t!=1) anss=anss/t*(t-1);
	return anss;
}
void get_v(int n)
{
	v.clear();
	if(!zs[n]) return;
	for(int i=2;i*i<=n;i++)
	{
		if(n%i==0)
		{
			v.push_back(i);
			if(i*i!=n)
			v.push_back(n/i);
		}
	}
}
void solve(int n)
{
	int p=euler(n);
	//printf("p=%d\n",p);
	get_v(p);
	int flag=0;
	for(int i=2;i<n;i++)
	{
		int flag1=0;
		if(quick_mod(i,p,n)!=1) continue;
		for(int j=0;j<v.size();j++)
		{
			if(quick_mod(i,v[j],n)==1)
			{
				flag1=1;
				break;
			}
		}
		if(!flag1)
		{
			flag=1;
			ans[0]=i;
			break;
		}
	}
	if(!flag)
	{
		printf("-1\n");
		return;
	}
	int cnt=1;
	for(int i=2;i<p;i++)
	{
		if(gcd(i,p)==1)
		{
			ans[cnt++]=quick_mod(ans[0],i,n); 
		}
	}
	sort(ans,ans+cnt);
	int t=unique(ans,ans+cnt)-ans;
	for(int i=0;i<t;i++)
	{
		if(i) printf(" ");
		printf("%d",ans[i]);
	}
	printf("\n");
}
int main()
{
	int n;
	memset(zs,0,sizeof(zs));
	zs[0]=zs[1]=1;
	for(int i=2;i<maxn;i++)
	{
		if(!zs[i])
		{
			for(int j=i<<1;j<maxn;j+=i)
			zs[j]=1;
		}
	}
	while(scanf("%d",&n)==1)
	{
		if(n==2)
		printf("1\n");
		else if(n==4)
		printf("3\n");
		else if(!vj(n))
		printf("-1\n");
		else solve(n);
	}
}