欧拉函数(模板及应用)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值