题目链接:(http://poj.org/problem?id=2407)
题意:
给出一个整数n,求小于n的与n 互素的个数。其实就是 欧拉函数的应用。
欧拉函数的讲解,有个讲解的很好,链接给出来:http://blog.csdn.net/dt2131/article/details/52116264
代码如下:
#include <iostream>
#include<algorithm>
#include<iomanip>
#include<cstring>
using namespace std;
int main()
{
int n;
while(cin>>n&&n)
{
int tmp=n;
for(int i=2;i<=n;i++)//枚举每个数
if(n%i==0)//如果这个数是因数
{
tmp-=tmp/i;//套公式x*(1-1/pi)=x-x/pi,
while(n%i==0)//删除所有i因子
n/=i;
}
if(n>1)//筛后有剩余的数,说明这个数也是一个质因子
tmp-=tmp/n;
cout<<tmp<<endl;
}
}
欧拉函数,表示小于等于n中与n互质的整数个数,即满足gcd(n,i)==1的整数个数,其中i>=1&&i<=n;
计算公式:欧拉函数φ(x)=x(1-1/p(1))(1-1/p(2))(1-1/p(3))(1-1/p(4))…..(1-1/p(n)) 中p(1),p(2)…p(n)为x的所有质因数。
下述代码中可以看出没有刻意去找素数,原因是只需找出一个素因子之后把他除干净,就能保证所有因子都是素数。(原因可以想想唯一分解定理:任意一个数都可以表示成素数的乘积)
两个计算模板:
直接求欧拉函数:
int euler(int n){ //返回euler(n)
int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);//这儿等同于res*(1-i/1)
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1); //筛选后有剩余,这个数也是一个质因子
return res;
}
1-n中的所有欧拉函数值:
Init(){
euler[1]=1;
for(int i=2;i<Max;i++)
euler[i]=i;
for(int i=2;i<Max;i++)
if(euler[i]==i)
for(int j=i;j<Max;j+=i)
euler[j]=euler[j]/i*(i-1);
}