题意:
给你一个数
,再给你
个数,问你小于
且至少是这
个数某个的倍数的数字有多少个。
思路
很明显的容斥,一开始用
写,已知Wa,后来看别人博客才知道有0输入,所以要去掉0…真坑。
做法
ll f[N];
ll ans;
ll n, m;
ll LCM(ll a, ll b) { return a / __gcd(a, b) * b; }
void dfs(ll id, ll step, ll p, ll s)
{
if (s == step)
{
if (step & 1)
ans += (n - 1) / p;
else
ans -= (n - 1) / p;
//cout<<p<<endl;
return;
}
if (id > m + 1)
return;
for (ll i = id; i <= m; ++i)
{
dfs(i + 1, step, LCM(p, f[i]), s + 1);
}
}
int main()
{
while (cin >> n >> m)
{
ans = 0;
int idx = 0;
for (ll i = 1; i <= m; ++i)
{
ll a;
cin >> a;
if(a) f[++idx] = a;
}
m = idx;
for (ll i = 1; i <= m; ++i)
dfs(1, i, 1, 0);
cout << ans<< endl;
}
}
二进制枚举做法
ll f[N];
ll ans;
ll n, m;
ll lowbit(ll x) { return x & (-x); }
ll LCM(ll a, ll b) { return a / __gcd(a, b) * b; }
int main()
{
while (cin >> n >> m)
{
ans= 0;
int idx = -1;
for (ll i = 0; i < m; ++i)
{
ll a;
cin >> a;
if (a)
f[++idx] = a;
}
m = idx +1;
ll s = (1LL << m) - 1;
for (ll i = 1; i <= s; ++i)
{
ll temp = i;
ll cnt = 0;
while (temp)
{
temp -= lowbit(temp);
cnt++;
}
// cout<<cnt<<endl;
ll p = 1;
for (ll j = 0; j <= 10; ++j)
{
if ((i >> j) & 1)
p = LCM(p, f[j]);
}
if (cnt & 1)
ans += (n - 1) / p;
else
ans -= (n - 1) / p;
}
cout << ans<<endl;
}
}