hdu1796 How many integers can you find(容斥)

题意:
给你一个数 n n ,再给你 m m 个数,问你小于 n n 且至少是这 m m 个数某个的倍数的数字有多少个。
思路
很明显的容斥,一开始用 d f s dfs 写,已知Wa,后来看别人博客才知道有0输入,所以要去掉0…真坑。
d f s dfs 做法

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;
    }
}
发布了632 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_43408238/article/details/104053195