<题目链接>
题目大意:
给你m个数,其中可能含有0,问有多少小于n的正数能整除这个m个数中的某一个。
解题分析:
容斥水题,直接对这m个数(除0以外)及其组合的倍数在[1,n)中的个数即可,因为可能会重复计算,所以在叠加的时候进行容斥处理,下面用的是位运算实现容斥。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 ll n,m,arr[15]; 9 ll gcd(ll a,ll b){ 10 return b==0?a:gcd(b,a%b); 11 } 12 ll lcm(ll a,ll b){ 13 return a*b/gcd(a,b); 14 } 15 int main(){ 16 while(cin>>n>>m){ 17 int cnt=0; 18 for(int i=1;i<=m;i++){ 19 scanf("%lld",&arr[cnt]); 20 if(arr[cnt])cnt++; 21 } 22 ll sum=0; 23 for(int i=1;i<(1<<cnt);i++){ 24 ll res=1,tot=0; 25 for(int j=0;j<cnt;j++){ 26 if(i & (1<<j)){ 27 res=lcm(res,arr[j]); //注意这里将不同的数组合时,是求它们的lcm,而不是直接相乘 28 tot++; //组合的数个数,用于后面判奇偶 29 } 30 } 31 if(tot & 1)sum+=(n-1)/res; //题意不包含n 32 else sum-=(n-1)/res; 33 } 34 printf("%lld ",sum); 35 } 36 }
2019-02-09