UVA 10325 The Lottery 容斥原理
链接:UVA 10325 The Lottery
题意:给你两个正整数
,然后给你
个正整数
,让你找出
~
中有多少个数不是这
个数的倍数?
题解:显然,我们会想到用
减去
,但是这样会有一些元素会重复计算,我们就需要用容斥原理把重复计算的数减掉,像第一个样例:
,但是对于对于第二个样例:
,这时我们就要想什么样的数应该进行容斥,对于第二个样例来说,
的倍数应该被减去,
的倍数也被减去,那么什么样的数应该加进来呢?我们发现
被减过两次,
被减过一次,那么我们发现应该将
的加进来,即
,我们发现
,到此我们就可以得出结果:
.可以求出最终结果。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+100;
int a[maxn];
int num[maxn];
LL gcd(LL a, LL b)
{
if(b==0)
return a;
return gcd(b, a%b);
}
int main()
{
int n,m;
while(~scanf("%d%d", &n, &m))
{
int a[20];
for(int i = 1; i <= m;i++)
{
scanf("%d", &a[i]);
}
LL ans = 0;
//容斥枚举全部子集模板
for(int i = 0; i <(1<<m);i++)//1----
{
int cnt = 0;
LL d = 1;
for(int j = 1;j<=m;j++)//2----
{
if((i>>(j-1))&1)//3----
{
cnt++;
d = a[j]/gcd(a[j],d)*d;
}
}
if(cnt&1)
{
ans -= n/d;
}
else
{
ans += n/d;
}
}
printf("%lld\n", ans);
}
return 0;
}
//模板形式
{
for(int i = 0; i <(1<<m);i++)//1----
for(int j = 1;j<=m;j++)//2----
if((i>>(j-1))&1)//3----
}