【ybt金牌导航8-4-1】整数个数 / 欧拉函数例题

整数个数

题目链接:ybt金牌导航8-4-1

题目大意

给你一个数 n,求满足一下条件的数个数:
要小于 n,要不是 n 的约数,不能与 n 互质。

思路

你看到互质,自然会想到欧拉函数。

但是它是不能互质啊,而且它说不是约数也很烦。

那简单,我们容斥一下,用全部的(根据小于 n n n n − 1 n-1 n1 个)减去是 n n n 的约数 n n n 互质的个数就好了。

那算约数的时候你会把 n n n 也算作约数,但你前面的条件是小于 n n n,那就要继续容斥,这里算的是减的,那你就要加回一个 1 1 1

然后你算约数和算互质的时候会都算到 1 1 1,那也容斥,加回 1 1 1

那这样就可以直接减约数个数和互质个数再根据上面容斥就可以了。

接着就是怎么求互质个数,也就是欧拉函数要怎么算。

这里给出一种算单个的方法。
φ ( i ) = i × p 1 − 1 p 1 × . . . × p m − 1 p m \varphi(i)=i\times\dfrac{p_1-1}{p_1}\times...\times\dfrac{p_m-1}{p_m} φ(i)=i×p1p11×...×pmpm1
p i p_i pi 是它的质数因子)

原理大概就是它不能出现任何因子,而因子由素数因子构成。
然后就类似容斥,你某个质数 p i p_i pi 1 ∼ i 1\sim i 1i 划分成许多长度为 p i p_i pi 的区间,然后每个区间都有个位置不能选(就是那个位置是 p i p_i pi 的倍数)。
然后每个质数因子都这样,就是这个公式了。

代码

#include<cstdio>
#define ll long long

using namespace std;

ll n, ans;

ll phi(ll x) {//求n的phi值
	int re = x;
	for (int i = 2; i * i <= x; i++)
		if (n % i == 0) {
			re = re / i * (i - 1);
			while (n % i == 0) n /= i;
		}
	if (n >> 1)
		re = re / n * (n - 1);
	return re;
}

int main() {
	scanf("%d", &n);
	ans = n - 1;//满足小于 n 的有 n-1 个
	
	for (ll i = 1; i * i <= n; i++)//求 n 因子的个数
		if (n % i == 0) {
			ans -= 2;
			if (i * i == n) ans++;
		}
	ans++;//前面求的时候把 n 也算个进去,减多了,要加回去
	
	ans -= phi(n);//求与 n 互质的数的个数(n 的 phi 值)
	
	ans++;//求因子和求互质的地方都算了 1,重复了要加回去。
	
	printf("%lld\n", ans);
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值