1e9个兵临城下(容斥原理)

本文解析一道算法竞赛题目,通过容斥原理解决FF如何计算最少所需人数以应对NE及其团队的挑战。涉及算法竞赛、容斥原理及编程实现。

链接:https://ac.nowcoder.com/acm/contest/321/A
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

 “FF来训练!”“一定来!”

 

 

FF成天到晚咕了NE的训练。这可把NE急坏了。为了拯救ff的知识勺,拥有知识海的NE决定去现实gank一波FF,逼他训练。

可去gank了几波发现ff居然有着成千上万的小伙伴在帮助FF阻拦NE,这几次gank,NE都失败了。无奈之下痛定思痛,NE决定也带上自己的109个小伙伴去gankFF。

FF提前得知了这个消息,这可把FF急坏了.那可是109个人啊!

这时FF的小伙伴EN说:“FF莫慌,我这里有3盏BD哥的神灯,上面分别有一个素数,可以让编号被上面的数字整除的人昏睡过去,这样就可以大大削减NE的人数!”(FF所带的109个人分别被编号为1~109)

FF:“好!”。FF如同找到了救命稻草。但是由于只能削减一部分人数,FF需要召集的人数应该大于等于NE剩下的人数,但是时间紧急,FF算不出来了,你能告诉FF至少要准备多少人吗?

 

输入描述:

 

第一行包含一个正整数T(T<200)

之后的T行每行包含3个正整数,a,b,c(2<=a,b,c<106;a!=b,b!=c,c!=a;保证a,b,c为素数)

分别代表3盏神灯上的数字。

输出描述:

输出T行
每行一个整数,表示FF至少要准备的人数。

示例1

输入

复制

3
2 3 5
5 7 11
13 2 3

输出

复制

266666666
623376624
307692308

题解:

容斥原理

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using  namespace std;


int main()
{
	
	int T;
	cin>>T;
	for(int t=0;t<T;t++)
	{
		long long int a,b,c;
		scanf("%lld%lld%lld",&a,&b,&c);
		long long int sum=1000000000;
		long long int a1,a2,a3,a4,a5,a6,a7;
		a1=sum/a;
		a2=sum/b;
		a3=sum/c;
		a4=sum/(a*b);
		a5=sum/(a*c);
		a6=sum/(b*c);
		a7=sum/(a*b*c);
		//cout<<a1+a2+a3-a4-a5-a6+a7<<endl;
		long long int s=sum-(a1+a2+a3-a4-a5-a6+a7);
		cout<<s<<endl;
	  
		//cout<<sum<<endl;
	}
	
	return 0;
}

 

### 容斥原理的 C++ 实现 容斥原理是一种用于解决集合计数问题的重要方法,在编程竞赛和实际开发中有广泛应用。以下是基于给定引用的内容以及专业知识,详细介绍如何用 C++ 实现容斥原理。 #### 1. 基本概念 容斥原理的核心在于通过加减法来计算多个集合交集或并集中的元素数量。对于一组互不相同的质因数 \( p_1, p_2, \ldots, p_m \),可以通过枚举子集的方式统计满足条件的数量[^3]。 --- #### 2. C++ 实现代码 以下是一个完整的 C++ 实现示例: ```cpp #include <iostream> #include <vector> using namespace std; long long solve(long long n, const vector<int>& primes) { int m = primes.size(); long long res = 0; // 枚举所有可能的子集 (2^m 种状态) for (int mask = 1; mask < (1 << m); ++mask) { long long lcm = 1; int cnt = 0; // 计算当前掩码对应的 LCM 和因子个数 for (int i = 0; i < m; ++i) { if ((mask >> i) & 1) { if (__INT64_C(1e18) / lcm < primes[i]) { // 防止溢出 lcm = -1; break; } lcm *= primes[i]; ++cnt; } } if (lcm != -1 && lcm > 0) { long long cur = n / lcm; if (cnt % 2 == 1) { res += cur; } else { res -= cur; } } } return res; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<int> primes(m); for (int i = 0; i < m; ++i) { cin >> primes[i]; } cout << solve(n, primes) << endl; return 0; } ``` --- #### 3. 关键点解析 - **输入处理**: 输入两个参数 `n` 和 `m`,分别代表范围上限和质因数数组大小。随后读取长度为 `m` 的质因数列表。 - **核心逻辑**: - 使用位运算 `(1 << m)` 来遍历所有的子集组合。 - 对于每一个子集,计算其最小公倍数(LCM),并通过判断奇偶性决定是增加还是减少该部分的结果[^1]。 - 如果某个中间乘积超过数据范围,则跳过此子集以防止溢出[^2]。 - **输出结果**: 输出最终符合条件的数值总数。 --- #### 4. 应用场景举例 - **素数筛选优化**: 利用容斥原理可以快速求解区间 `[1,n]` 中无法被某些特定数字整除的数目。 - **组合数学问题**: 如在多组约束条件下寻找满足条件的排列组合方案。 - **概率计算**: 当涉及复杂事件的概率分析时,可以用容斥原理解决重叠区域的影响。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

black-hole6

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值