欧拉函数是求小于n的,与n互质的数(gcd == 1)的数目
如与9互质的数(< 9)有1,2,4,5,7,8
公式: 其中p1~pn是x的n个质因子,
特别的:φ(1)=1
12的质因子有2,3
φ(12) = 12*(1 - 1/2)*(1 - 1/3) = 4 (1,5,7,11)
求单个数的欧拉函数
int Euler(int n)
{
int ans = n,now = 2;//从2开始找n的质因子
while(n >1)
{
if(n %now == 0)//能进判断条件的now都是n的质因子
{
ans /= now;//因为n是now的倍数,除不会出现小数
ans *= (now-1);//先除后乘,防止出现小数,也可以避免溢出//欧拉公式φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pn)
while(n%now == 0)//除去n中是now的倍数的因子,也就是除去n中的非质数因子
n/= now;
}
now ++;
}
return ans;
}
打表求欧拉函数 O(nloglog(n))
int euler[maxn];
int euler_init(int n)
{
for(int i = 1; i <= n; i ++)//欧拉函数的第一个乘数是自己
{
euler[i] = i;
}
for(int i = 2; i <= n; i ++)
{
if(euler[i] == i)//如果euler[i] == i,说明这个数是质数,找它的倍数
{
for(int j = i; j <= n; j +=i)//利用欧拉函数,质数i是j的因子,则euler[j] *= (1-1/i);
{
euler[j] = euler[j]/i*(i-1);
}
}
}
}
欧拉函数+素数线性筛法 o(n)
const int maxn = 1e5;
int vis[maxn],euler[maxn],prime[maxn];//是不是素数,欧拉函数,第i个素数是
void prime_euler_init(int n)
{
int cnt=0;
euler[1]=1;
for(int i=2; i<=n; i++)
{
if(!vis[i])
{
prime[++cnt]=i;
euler[i]=i-1;
}
for(int j=1; j<=cnt&&prime[j]*i<=n; j++)
{
vis[i*prime[j]]=1;
if(i%prime[j])
{
euler[i*prime[j]]=euler[i]*(prime[j]-1);// 如果i mod p == 0, 那么 euler(i * p) == p * euler(i)
}
else
{
euler[i*prime[j]]=euler[i]*prime[j];//i mod p != 0, 那么 euler(i * p) == euler(i) * (p-1)
break;
}
}
}
}