欧拉函数
定义:对于一个正整数 n ,小于 n 且和 n 互质的正整数(包括 1)的个数,记作 φ(n)
比如:n = 8 时,有 1,3,5,7 与它互质,所以 φ(8) = 4
函数计算公式:φ(n)=n*(1-1/p1)*(1-1/p2)*...*(1-1/pn) ,其中p1,p2,...,pn位n的质因子
易知,如果n为质数,一定有 φ(n) = n-1
函数的几个性质:
1、φ(1)=1
2、φ(pk)=pk−pk−1=(p−1)⋅pk−1,其中p为质数
3、φ(mn)=φ(m)⋅φ(n),其中gcd(m,n)=1
欧拉定理:
若为正整数,且互素(即),则 。
换种说法就是 a^ φ(n) % n 恒等于 1.
特别的,当n是质数的时候,上式就变成了 ,它也叫费马小定理,但它是个单向定理,不能用这个同余证n是质数。
原根:
在时,定义对模的指数 为使 成立的最小的正整数。由欧拉定理知 一定小于等于 ,
若,则称是模的原根。
m的原根个数正好为φ(φ(m)) (在m是素数情况下进一步知原根的个数是φ(m-1) )
例:poj-1284 http://poj.org/problem?id=1284
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define N 1000005
int p[N];
void fun(){ //素数表
int i, j, k;
memset(p, 0, sizeof(p));
p[1] = 1;
for(i=2; i<=sqrt(N); i++){
for(j=2; j<=N/i; j++){
p[i*j] = 1;
}
}
}
int oula(int n){
int i, j, r, a;
r = n;
a = n;
for(i=2; i<=sqrt(n); i++){
if(!p[i]){
if(a%i==0){
r = r/i * (i-1);
while(a%i==0)
a /= i;
}
}
}
if(a>1)
r = r/a*(a-1);
return r;
}
int main(){
int n;
while(cin>>n){
// cout<<oula(oula(n))<<endl; //一般情况
cout<<oula(n-1)<<endl; //n为奇素数时
}
return 0;
}