ABC349F题解

思想

看到 LCM 想到质因数分解。

首先,我们先把 M 质因数分解了,根号复杂度刚好 1e8 级别。

然后我们发现一个很显然的性质:如果一个数不是 M 的因数那他肯定没用。

所以此处我们就把不是因数地踢掉。

我们惊奇地发现因为 M 的质因数分解最多 13 个不同的质数,然后我们就可以枚举这些因数直接判断每个数是不是他的倍数,这样就在 NlogM 的时间内做完了所有数的质因数分解。

此时,全部质因数的个数最多 13

那我们直接状压,

我们从左到右枚举这个序列,遇到每个数就把对应质因数分解的状压的数组加一,每次再遍历整个集合,暴力更新。

这样搞的话复杂度是 N×213,看起来会爆,但 2e5*8e3=1.6e9,2s时限,加上取模卡卡常,AT 评测机这么强悍,好像都能过。

代码

// Coded by LightningCreeper.

#include <bits/stdc++.h>
using namespace std;

#define int long long

constexpr int MAXN = 2e5 + 5;

int n, m, tmp, a[MAXN], t[MAXN], f[MAXN];
bool flag[MAXN];

vector<int> prime;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m;

    tmp = m;

    prime.clear();
    for (int x = 2; x * x <= tmp; x++) {
        int now = 1;
        while (tmp % x == 0) {
            tmp /= x;
            now *= x;
        }
        if (now == 1)
            continue;
        prime.push_back(now);
    }
    if (tmp > 1)
        prime.push_back(tmp);

    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (m % a[i] != 0)
            flag[i] = true;
        else
            for (int j = 0; j < prime.size(); j++)
                if (a[i] % prime[j] == 0)
                    t[i] |= 1ll << j;
    }

    for (int i = 1; i <= n; i++) {
        if (flag[i])
            continue;
        for (int j = (1ll << prime.size()) - 1; j >= 0; j--) {
            f[j | t[i]] += f[j];
            if (f[j | t[i]] >= 998244353)
                f[j | t[i]] -= 998244353;
        }
        f[t[i]]++;
        f[t[i]] = (f[t[i]] == 998244353 ? 0 : f[t[i]]);
    }
    cout << f[(1ll << prime.size()) - 1] << endl;

    return 0;
}

// Everyone cannot copy this code to judge.
posted @   LightningCreeper  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示