一个数的欧拉函数是指不超过这个数且与此数互质的正整数的个数。
1、如果n是质数,则φ(n) = n - 1
2、如果n为两个互质的数a,b的乘积,则φ(a*b) = φ(a) * φ(b)
与a*b互质的数,只能是既与a互质(有φ(a)个),又与b互质(有φ(b)个),所以一共有φ(a) * φ(b)个
3、如果n为某一个质数p的幂次p^a,则φ(p^a) = (p-1)*p^(a-1)
在[1,p^a-1]范围内能被p整除的数一共有p^(a-1)-1个数,区间总数是p^a-1个,所以φ(p^a) = p^a-p^(a-1) = (p-1)*p^(a-1)
那么对于任意数求它的欧拉函数。
n = p1^k1 * p2^k2 * p3^k3*....*pn^kn
φ(n) = φ(p1^k1) * φ(p2^k2)*...*φ(pn^kn)
= (p1-1)*p1^(k1-1)*(p2-1)*p2^(k2-1)*....
= p1^k1 * p2^k2 * p3^k3*....*pn^kn * (1-1/p1)*(1-1/p2)*...*(1-1/pn)
= n * (1-1/p1)*(1-1/p2)*...*(1-1/pn)
1、单个欧拉函数的计算 POJ 2407
Phi(n) = ∏(pi-1) * pi^(a-1)
求出每一个质因子和幂次,由公式计算得到。
LL cal( LL x )
{
LL ans = 1;
for( int i = 2; i*i <= x; i++ )
{
if ( x % i == 0) //找到一个质因子
{
ans*=i-1;
x /= i;
while( x % i == 0 )
{
ans *= i;
x /= i;
}
}
}
if ( x > 1 ) ans*=(x-1);
return ans;
}
2、欧拉函数线性筛( NlogN ) POJ 3090
找到n的最小质因数k phi( p ^a ) = (p-1)* p^( a - 1 )
如果n只能整除k,phi(n) = phi( n/k )*(k-1)
否则 phi(n) = phi(n/k)*k
void getphi(int n)
{
rep(i,1,n) mindiv[i] = i; //记录i的最小质因数
for(int i = 2; i*i <= n; i++)
if ( mindiv[i] == i )
{
for(int j = i*i; j <= n; j+=i) mindiv[j] = i;
}
phi[1] = 1;
rep(i,2,n)
{
phi[i] = phi[i/mindiv[i]];
if ( ( i / mindiv[i] ) % mindiv[i] == 0 ) phi[i] *= mindiv[i]; //还可以再除
else phi[i] *= ( mindiv[i] - 1 );
}
}
3、欧拉筛O(N)
int prime[maxn/5];
int f[maxn];
bool isprime[maxn];
void init()
{
int count = 0;
Clean(isprime,true);
for( int i = 2; i <= 5000000; i++ )
{
if ( isprime[i] )
{
prime[++count] = i;
f[i] = i - 1;
}
for( int j = 1; j <= count; j++ )
{
if ( i * prime[j] > maxn-5 ) break;
isprime[ i * prime[j] ] = false;
if ( i % prime[j] )
f[ i * prime[j] ] = (prime[j]-1) * f[i];
else
{
f[ i * prime[j] ] = (prime[j]) * f[i];
break;
}
}
}
}