首先指出欧拉函数是小于等于n的数中与n互质(互质是公约数只有1的两个整数)的数的数目。
单个筛欧拉函数值:
1的欧拉函数值为1,1与任何数都互质。
(φ(1)=1)
int phi(int n)
{
int res=n,a=n;
for(int i=2;i*i<=a;i++)
{
if(a%i==0)
{
res=res/i*(i-1);//先除后乘防止溢出
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
一个近视线性筛法的模板
void Euler()
{
phi[1]=1;
for(int i=2;i<M;i++)
if(!phi[i])//没有被筛过说明是质数
for(int k=i;k<M;k+=i)
{
if(!phi[k]) phi[k]=k;
phi[k]=phi[k]/i*(i-1);//欧拉函数公式的实现
}
return ;
}
其中M是自己根据题意设定的一个最大范围数。
线性筛素数加欧拉函数
#include<bits/stdc++.h>
#define N 600000
using namespace std;
int n;
int phi[N+10],prime[N+10],tot,ans;
bool mark[N+10];
int main()
{
int i,j;
phi[1]=1;//1的欧拉函数值是1
for(i=2; i<=N; i++)
{
if(!mark[i])//如果是素数
{
prime[++tot]=i;//第一个素数
phi[i]=i-1;//素数的phi就是i-1
}
for(j=1; i*prime[j]<=N&&j<=tot; j++)
{
mark[i*prime[j]]=1;//i*prime[j]不是素数
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
{
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
int k;
cin>>k;
if(mark[k])
cout<<"ok"<<endl;
else
cout<<phi[k];
}
来看一道题:
题目大意:
给你一个整数N,求范围小于N中的整数中,与N的最大公约数大于1的整数的个数。
欧拉函数求出的是小于n中与n最大公约数为1的个数所以
ans = n - φ(N) - 1。