问题:魔镜给小明m个数字(a1、a2 …… am)和一个整
数n,魔镜定义:如果有一个数,是这m个数字里面任意一
个数的倍数,那么这个数称为LuckyNumber。而小明会的题
数为[1,n]闭区间内LuckyNumber的数量。(0 < m < 15)
那么请你帮小明计算一下他会的题目数。
#include <bits/stdc++.h>
using namespace std;
/*
问题:魔镜给小明m个数字(a1、a2 …… am)和一个整
数n,魔镜定义:如果有一个数,是这m个数字里面任意一
个数的倍数,那么这个数称为LuckyNumber。而小明会的题
数为[1,n]闭区间内LuckyNumber的数量。(0 < m < 15)
那么请你帮小明计算一下他会的题目数。
a1 a2 a3 ... am
2 3 4
1 2 3 4 5 6 ... n
1 +
a1 n/a1
a2 n/a2
..
.
2 -
a1 a2 n/lcm(a1, a2)
a1 a3 n/lcm(a1, a3)
..
.
3
a1 a2 a3 n/lcm(a1, a2, a3)
a1 a2 a4 n/lcm(a1, a2, a4)
..
.
...
...
..
*/
ll gcd(ll a, ll b){
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b){
return a / gcd(a, b) * b;
}
int a[N];
int main(){
int n, m; scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++) scanf("%d", &a[i]);
ll ans = 0;
for(int i = 1; i < (1 << m); i++){ // 相当于枚举所有的情况 o(2^n*n)
int cnt = 0; ll tmp = 1;
for(int j = 0; j < n ;j++){ // a[j]
if(i >> j & 1) {
cnt ++;
tmp = lcm(tmp, a[j]);
}
}
if(cnt & 1) ans += n / tmp;
else ans -= n / tmp;
}
printf("%lld\n", ans);
return 0;
}