C/C++容斥定理

问题:魔镜给小明m个数字(a1、a2 …… am)和一个整
数n,魔镜定义:如果有一个数,是这m个数字里面任意一
个数的倍数,那么这个数称为LuckyNumber。而小明会的题
数为[1,n]闭区间内LuckyNumber的数量。(0 < m < 15)
那么请你帮小明计算一下他会的题目数。

#include <bits/stdc++.h>
using namespace std;

/*
问题:魔镜给小明m个数字(a1、a2 …… am)和一个整
数n,魔镜定义:如果有一个数,是这m个数字里面任意一
个数的倍数,那么这个数称为LuckyNumber。而小明会的题
数为[1,n]闭区间内LuckyNumber的数量。(0 < m < 15)
那么请你帮小明计算一下他会的题目数。

a1 a2 a3 ... am
2  3  4 


1 2 3 4 5 6 ... n 

  
 
1  +
a1  n/a1 
a2  n/a2
..  
.


2 -
a1 a2 n/lcm(a1, a2)
a1 a3 n/lcm(a1, a3)
..
.

3 
a1 a2 a3 n/lcm(a1, a2, a3)
a1 a2 a4 n/lcm(a1, a2, a4)
..
.


...
...
..

*/

ll gcd(ll a, ll b){
	return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b){
	return a / gcd(a, b) * b;
}

int a[N];
int main(){
	int n, m; scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++) scanf("%d", &a[i]);
	ll ans = 0; 
	for(int i = 1; i < (1 << m); i++){ // 相当于枚举所有的情况 o(2^n*n)  
		int  cnt = 0; ll tmp = 1;
		for(int j = 0; j < n ;j++){    // a[j] 
			if(i >> j & 1) {
				cnt ++;
				tmp = lcm(tmp, a[j]); 
			}
		}	
		if(cnt & 1) ans += n / tmp;
		else ans -= n / tmp; 
	}
	printf("%lld\n", ans); 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值