容斥原理的应用。
推导过程类似于欧拉函数的推导过程,但是不能直接用公式;
所以利用二进制模拟的运算。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b)
{
if(!b) return a;
gcd(b,a%b);
}
//求最小公倍数
LL Lcm(LL a,LL b)
{
LL t=gcd(a,b);
return a/t*b; //防止越界,先除后乘
}
int M[20],m,n;
LL solve1()
{
LL i,j,k,ans=n;
for(i=1;i<=(1<<m)-1;i++)
{
int cnt=0,m1=0;
LL mult=1; //mult必须定义为longlong类型,否则就会出错
j=i;
while(j)
{
if(j&1)
{
cnt++;
mult=Lcm(mult,M[m1]);
}
m1++;
j=j>>1;
}
int cur=n/mult;
if(cnt%2==1)
ans-=cur;
else
ans+=cur;
}
return ans;
}
LL solve()
{
LL i,j,k,ans=0;
for(i=1;i<(1<<m);i++)
{
int cnt=0;
LL mult=1;
for(j=0;j<m;j++)
{
if(i&(1<<j))
{
cnt++;
mult=Lcm(mult,M[j]);
}
}
int cur=n/mult;
if(cnt%2)
ans+=cur;
else
ans-=cur;
}
return n-ans;
}
int main()
{
int i,j;
while(cin>>n>>m)
{
memset(M,0,sizeof(M));
for(i=0;i<m;i++)
cin>>M[i];
LL ans=solve1();
cout<<ans<<endl;
}
return 0;
}