您的位置:首页 > 理论基础 > 计算机网络

http://acm.pku.edu.cn/JudgeOnline/problem?id=1284 (原根)

2010-08-11 18:52 525 查看
]/*
poj 1284 原跟
设h为一整数,n为一正整数,(h,n)=k,适合h^k=1(mod n)的最小正整数k叫做h对n的次数。如果k=φ(n),则此时h被称为模n的原根。
1773年,欧拉证明了素数P有原根。1785年,勒让德证明:设k|(p-1),恰有φ(k)个模p互不同余的数对模p的次数为k。
大家可以去搜索一下“二次剩余”
p是奇素数,如果{xi%p | 1 <= i <= p - 1} = {1,2,...,p-1},则称x是p的原根.
给出一个p,问它的原根有多少个.
 {xi%p | 1 <= i <= p - 1} = {1,2,...,p-1} 等价于 {xi%(p-1) | 1 <= i <= p - 1} = {0,1,2,...,p-2},即为(p-1)的完全剩余系
若x,x2...x(p-1)是(p-1)的完全剩余系,
根据定理,可以推出若gcd(x, p-1) = 1时, (1,x,...,x(p-2))也是(p-1)的完全剩余系
因为若xi != xj (mod p-1),那么x*xi != x*xj (mod p-1),与条件m矛盾,所以 xi = xj (mod p-1),
由此可以确定答案为EulerPhi(p-1)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 65539;
bool hash
;
int prime[N / 2];
int p;
inline void Prime(){
memset(hash, false, sizeof(hash));
int tt = (int)sqrt(1.0 * N);
for(int i = 2; i <= tt; i++)
if(!hash[i])
for(int j =2; j * i < N; j++)
hash[i *j] = true;
p = 0;
for(int i = 2; i < N; i++)
if(!hash[i])
prime[p++] = i;
}
inline int Euler(int n){
int temp = n;
int sum = n;
for(int i = 0; i < p && prime[i] <= temp; i++){
if(temp % prime[i] == 0){
sum = sum / prime[i] * (prime[i] - 1);
while(temp % prime[i] == 0)
temp /= prime[i];
}
}
if(temp > 1)
sum = sum / temp * (temp - 1);
return sum;
}
int main(){
int n;
Prime();
while(scanf("%d", &n) != EOF){
printf("%d/n", Euler(n- 1));
}
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐