题目给一个数字集合,问有多少个小于n的正整数能被集合里至少一个元素整除。
当然是容斥原理来计数了,计算1个元素组合的有几个减去2个元素组合的LCM有几个加上3个元素组合的LCM有几个。注意是LCM。
- 而[1,n]中能被x整除的数字有$ lfloor frac nx floor$个,因为设有$t$个,$x imes t leqslant n$。
- 计算多个数LCM利用:$lcm(a,b)=a/gcd(a,b) imes b $,$lcm(a,b,c)=lcm(a,lcm(b,c))$
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int gcd(int a,int b){ 5 if(b==0) return a; 6 return gcd(b,a%b); 7 } 8 int lcm(int a,int b){ 9 return a/gcd(a,b)*b; 10 } 11 int getCnt(int s){ 12 int res=0; 13 for(int i=0; i<10; ++i){ 14 if((s>>i)&1) ++res; 15 } 16 return res; 17 } 18 int main(){ 19 int n,m,a[10]; 20 while(~scanf("%d%d",&n,&m)){ 21 --n; 22 int t=0; 23 while(m--){ 24 scanf("%d",&a[t]); 25 if(a[t]) ++t; 26 } 27 m=t; 28 int ans=0; 29 for(int i=1; i<(1<<m); ++i){ 30 int res=1; 31 for(int j=0; j<m; ++j){ 32 if(a[j]==0 || ((i>>j)&1)==0) continue; 33 res=lcm(res,a[j]); 34 } 35 if(getCnt(i)&1) ans+=n/res; 36 else ans-=n/res; 37 } 38 printf("%d ",ans); 39 } 40 return 0; 41 }