poj 1284 Primitive Roots(原根+欧拉函数)

http://poj.org/problem?id=1284


原根

题意:对于奇素数p,假设存在一个x(1<x<p),(x^i)%p两两不同(0<i<p),且解集等于{1,2....,p-1}。

称x是p的一个原根。

输入p问p的原根有多少个。


直接枚举的,TLE了。

看到discuss里面说是求原根。答案直接是phi[p-1]。百度百科上直接就给出答案了。m有原根的充要条件是m= 1,2,4,p,2p,p^n,当中p是奇素数,n是随意正整数。它所含原根的个数是phi[phi[m]],由于phi[m]=m-1,所以答案是phi[m-1]。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;

const int maxn = 65540;
int flag[maxn];
int prime[maxn];
int phi[maxn];

void init()
{
	memset(flag,0,sizeof(flag));
	phi[1] = 1;
	prime[0] = 0;
	for(int i = 2; i < maxn; i++)
	{
		if(flag[i] == 0)
		{
			phi[i] = i-1;
			prime[++prime[0]] = i;
		}
		for(int j = 1; j <= prime[0]&&prime[j]*i<maxn; j++)
		{
			flag[prime[j]*i] = 1;
			if(i%prime[j] == 0)
				phi[i*prime[j]] = phi[i] * prime[j];
			else
				phi[i*prime[j]] = phi[i] * (prime[j]-1);
		}
	}
}
int p;
int main()
{
	init();
	while(scanf("%d",&p) != EOF)
	{
		printf("%d
",phi[p-1]);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/mfmdaoyou/p/7298228.html