1.欧拉函数:
用于求解 [1,n] 中与n互质的数的个数的函数,与n互质的数就是与其最大公约数为1的数,即小于N的整数中,与N的最大公约数为1的数的个数,记作φ(N)。
2.标准模板:
int Euler(int n){
int res = n;
for(i= 2; i<= n/i; i++){
if(n % i == 0){
res = res / i* (i-1); //防止中间数据溢出
while(n % i == 0)
n /= i;
}
}
if(n>1)
res = res / n * (n-1);
return res;
}
3. 模板应用:
① HDU 1286 找新朋友
题目大意:
求与N的最大公约数为1的数的个数
解题思路:
直接套用欧拉模板
代码如下:
#include<stdio.h>
int Euler(int n){
int res = n;
int i;
for(i= 2; i<= n/i; i++){
if(n % i == 0){
res = res / i* (i-1); //防止中间数据溢出
while(n % i == 0)
n /= i;
}
}
if(n>1)
res = res / n * (n-1);
return res;
}
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%d\n",Euler(n));
}
return 0;
}
②HDU 1787 GCD Again
题目大意:
求小于N的整数中,与N的最大公约数大于1的整数的个数。
解题思路:
N - φ(N) - 1 (φ(N) 即 与N的最大公约数为1的数的个数)
代码如下:
#include<stdio.h>
int Euler(int n){
int res = n;
int i;
for(i= 2; i<= n/i; i++){
if(n % i == 0){
res = res / i* (i-1); //防止中间数据溢出
while(n % i == 0)
n /= i;
}
}
if(n>1)
res = res / n * (n-1);
return res;
}
int main(){
int n;
while(scanf("%d",&n)&&n){
printf("%d\n",n-Euler(n)-1);
}
return 0;
}
③HDU 3501 Calculation 2
题目大意:
求小于n的与n不互质的数的和
解题思路:
设小于n且与n互质数的数字的和为sum,根据欧拉函数性质:sum=Eular(n)*n/2,而1~(n-1)的和为(n-1)^n/2,因此结果为 (n-1)^n/2 - Eular(n)*n/2(数据太大,注意用long long型)
代码如下:
#include<stdio.h>
#define ll long long
ll Euler(ll n){
ll res = n;
ll i;
for(i= 2; i<= n/i; i++){
if(n % i == 0){
res = res / i* (i-1); //防止中间数据溢出
while(n % i == 0)
n /= i;
}
}
if(n>1)
res = res / n * (n-1);
return res;
}
int main(){
ll n;
while(scanf("%lld",&n)&&n){
ll sum = Euler(n) * n / 2;
ll ans = (n-1) * n / 2 - sum;
printf("%lld\n",ans%1000000007);
}
return 0;
}