HDU1796 How many integers can you find 容斥原理/dfs

题源:https://vjudge.net/problem/13388/origin
题意:给你数n,m;再给你m个数,问你从1~(n-1)中有多少个数可以被m集合中任意一个数整除。m<=20.
思路:考虑到m很小,所以直接深搜即可。核心思想是容斥,和算年份那个(LightOJ1414)差不多。搜索到奇数层时加上,偶数层时减去。 ans便是最终答案。
下面是核心代码:

void dfs(int p,ll lcm,int depth) {
	//p是当前枚举到哪一个了 lcm是当前所有数的最小公倍数
	//depth是枚举到的深度
	if(depth&1) ans+=(n-1)/lcm;//这两行的计算步骤很重要!
	else ans-=(n-1)/lcm;
	for(int i=p+1; i<=cnt; i++) {
		ll lcm2=Lcm(lcm,num[i]);
		dfs(i,lcm2,depth+1);
	}
	return;
}

下面是全部代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
#define MID (t[k].l+t[k].r)>>1
#define cl(a,b) memset(a,b,sizeof(a))
#define dbg printf("aaa\n")
using namespace std;
//HDU1796
int n,m;
ll num[30];//也可用二进制枚举 不过感觉二进制有点麻烦
ll cnt,ans;//cnt记录去掉0之后有多少个!!!
ll Lcm(ll a,ll b) {
	return a/__gcd(a,b)*b;//先除 防止爆
}
void dfs(int p,ll lcm,int depth) {
	//p是当前枚举到哪一个了 lcm是当前所有数的最小公倍数
	//depth是枚举到的深度
	if(depth&1) ans+=(n-1)/lcm;
	else ans-=(n-1)/lcm;
	for(int i=p+1; i<=cnt; i++) {
		ll lcm2=Lcm(lcm,num[i]);
		dfs(i,lcm2,depth+1);
	}
	return;
}
int main() {
	while(cin>>n>>m) {
		ans=0;
		cnt=0;
		cl(num,0);
		for(int i=1; i<=m; i++) {
			int temp;
			cin>>temp;//如果不是0 才计入 你写反了!!!
			if(temp) num[++cnt]=temp;
		}
		for(int i=1; i<=cnt; i++) {
			dfs(i,num[i],1);
		}
		cout<<ans<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值