题解:SP6285 NGM2 - Another Game With Numbers

蓝有点过于虚高了。

Solution SP6285

Idea

因为 kk 只有 1515,考虑状压。

正难则反,我们考虑求 [1,n][1,n] 中可以被任意一个 aia_i 整除的数的数量。

显然我们可以处理出每一个集合的每个数的 lcm\operatorname{lcm}。然后你会发现可以被这个集合所有数整除的数的个数是 nlcm{S}\lfloor\dfrac{n}{\operatorname{lcm}\{S\}}\rfloor

考虑容斥:显然 ansans 是可以被含有一个数的集合的所有数整除的个数减去它们重合的部分,也就是可以被含有两个数的集合的所有数整除的个数。然后两个数的集合也有重复(三个数的集合),不断循环得到容斥式子:

  • Smod2=0|S|\mod 2=0,则 ans=ansnlcm{S}ans=ans-\lfloor\dfrac{n}{\operatorname{lcm}\{S\}}\rfloor
  • Smod2=1|S|\mod 2=1,则 ans=ans+nlcm{S}ans=ans+\lfloor\dfrac{n}{\operatorname{lcm}\{S\}}\rfloor

于是做完了。

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=15;
int n,k;
ll a[N],ans;
int main(){
	scanf("%d%d",&n,&k);
	for(int i=0;i<k;i++){
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<(1<<k);i++){
		ll res=1;
		int cnt=0;
		for(int j=0;j<k;j++){
			if(i&(1<<j)){
				res=res/__gcd(a[j],res)*a[j];
				cnt++;
			} 
		}
		if(cnt&1)ans+=n/res;
		else ans-=n/res;
	}
	printf("%d\n",n-ans);
	return 0;
}
posted @ 2024-10-24 19:49  Weslie_qwq  阅读(12)  评论(0)    收藏  举报  来源