题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1836
题目大意:
给N个整数,和一个整数M。求小于等于M的非负整数(1~M)中能被这N个数中任意一个
整除的数的个数。
解题思路:
设S1为1~M中能被第一个整数A1整除的集合,S2为1~M中能被第二个整数A2整除的集合。
……
Sn为1~M中能被第N个整数An整除的集合。然后每个集合个数,其实就是M / An。
再根据容斥原理,求集合并集的元素个数即可。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
LL N,M,A[20];
LL GCD(LL a,LL b)
{
if(b == 0)
return a;
return GCD(b, a%b);
}
LL LCM(LL a, LL b)
{
return a / GCD(a,b) * b;
}
LL Solve()
{
LL ans = 0;
for(int i = 1; i < (1 << N); ++i)
{
LL odd = 0, Lcm = 1;
for(int j = 0; j < N; ++j)
{
if((1 << j) & i)
{
odd++;
Lcm = LCM(Lcm,A[j]);
}
}
if(odd & 1)
ans += M/Lcm;
else
ans -= M/Lcm;
}
return ans;
}
int main()
{
while(~scanf("%lld %lld",&N,&M))
{
for(int i = 0; i < N; ++i)
scanf("%lld",&A[i]);
printf("%lld\n",Solve());
}
return 0;
}