/* 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[N]; 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)); } }