欧拉函数定义:定义:对于正整数n,小于n且与n互质的正整数(包括1)的个数
剩余类:全体整数按其对m同余的数归为一类
完全剩余系:在每个对模m同余的剩余类选出一个数构成拥有m个元素的集合
简化剩余系:在模m的每个剩余类中取出一个和m互质的数构成的集合
(一个剩余类中的数要么都和m互质要么都不互质)
把对模m的简化剩余系的元素个数成为m的欧拉函数,记为Φ(m)
Φ(1)取值是0还是1由题判断。将m分解质因数,令所有质因数为p1、p2…pn
φ(n)=n*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(1-1/pn)
如:1~n中,p是n的质因子,2p,3p…(n/p)p都是n的质因子共有n/p个;q也是n的质因子,2q,3q…(n/q)q都是n的质因子共有n/q个
一个个数去求欧拉函数过慢,有一个较好的筛法:
设arr[11],arr[1]=1,arr[2]=2…arr[10]=10,
对于下标时2的倍数的每个元素分别乘(1-1/2),arr[2]=1,arr[4]=2…arr[10]=5;
对于下标时3的倍数的每个元素分别乘(1-1/3),arr[3]=2,arr[6]=2,arr[9]=6;
…
数组中每个元素都得到运算,当然要预先大号素数表
精简的用筛法求欧拉函数的模板:
//初始化eu[1]=0,请注意根据实际情况做出更改
//下面得出2~ 10000的欧拉函数
const int Max = 10001;
int eu[Max];
void eular( )
{
for(int i=2;i<Max;i++)
if (!eu[i])
for(int j=i;j<Max;j+=i)
{
if (!eu[j])eu[j]=j;
eu[j] =eu[j]/i*(i-1);
}
}
HDU1286(欧拉函数入门基础)
Problem Description
新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。
Input
第一行是测试数据的组数CN(Case number,1<CN<10000),接着有CN行正整数N(1<n<32768),表示会员人数。
Output
对于每一个N,输出一行新朋友的人数,这样共有CN行输出。
Sample Input
2
25608
24027
Sample Output
7680
16016
if(n>1)ans-=ans/n是为了保证我们已经除完了n的所有的素因子,有可能还会出现一个我们未除的因子,如果结尾出现n>1 ,说明我们还剩一个素因子没有除
#include<stdio.h>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int oula(int n){
int ans=n,k=n;//开始设所有人都跟他互质
for(int i=2;i<=sqrt(k);i++)//大于1的公约数
{
if(n%i==0)//约数关系,是老朋友
{
ans-=ans/i;//公式:结果=ans(1-1/i),变幻了一下
while(n%i==0)//如2
n/=i;
}
}
if(n>1)
ans-=ans/n;
return ans;
}
int main(){
int t,n;
cin>>t;
while(t--){
cin>>n;
int ans=oula(n);
cout<<ans<<endl;
}
return 0;
}