結果
| 問題 | No.2313 Product of Subsequence (hard) |
| ユーザー |
SnowBeenDiding
|
| 提出日時 | 2026-01-31 19:59:07 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 5,235 bytes |
| 記録 | |
| コンパイル時間 | 9,253 ms |
| コンパイル使用メモリ | 436,416 KB |
| 実行使用メモリ | 44,596 KB |
| 最終ジャッジ日時 | 2026-01-31 19:59:28 |
| 合計ジャッジ時間 | 18,747 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 10 TLE * 1 -- * 16 |
ソースコード
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <atcoder/all>
#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
using namespace atcoder;
using namespace std;
typedef long long ll;
using mint = modint998244353;
vector<ll> divisor(ll n) {
auto mod_mul = [](ll a, ll b, ll mod) -> ll {
return (__int128)a * b % mod;
};
auto mod_pow = [&](ll base, ll exp, ll mod) -> ll {
ll result = 1;
base %= mod;
while (exp) {
if (exp & 1) result = mod_mul(result, base, mod);
base = mod_mul(base, base, mod);
exp >>= 1;
}
return result;
};
auto is_prime = [&](ll num) -> bool {
if (num < 2) return false;
int smallPrimes[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
for (int p : smallPrimes) {
if (num == p) return true;
if (num % p == 0) return false;
}
ll d = num - 1;
int s = 0;
while ((d & 1) == 0) {
d /= 2;
s++;
}
ll testPrimes[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
for (ll a : testPrimes) {
if (a % num == 0) continue;
ll x = mod_pow(a, d, num);
if (x == 1 || x == num - 1) continue;
bool composite = true;
for (int i = 0; i < s - 1; i++) {
x = mod_mul(x, x, num);
if (x == num - 1) {
composite = false;
break;
}
}
if (composite) return false;
}
return true;
};
function<ll(ll)> pollard_rho;
pollard_rho = [&](ll num) -> ll {
if (num % 2 == 0) return 2;
mt19937_64 rng(random_device{}());
uniform_int_distribution<ll> dist(2, num - 2);
ll x = dist(rng), y = x, c = dist(rng), d = 1;
auto f = [&](ll x, ll c, ll mod) -> ll {
return (mod_mul(x, x, mod) + c) % mod;
};
while (d == 1) {
x = f(x, c, num);
y = f(y, c, num);
y = f(y, c, num);
d = gcd(abs(x - y), num);
if (d == num) return pollard_rho(num);
}
return d;
};
function<void(ll, vector<ll> &)> factorize;
factorize = [&](ll num, vector<ll> &factors) {
if (num == 1) return;
if (is_prime(num)) {
factors.push_back(num);
return;
}
ll factor = pollard_rho(num);
factorize(factor, factors);
factorize(num / factor, factors);
};
vector<ll> factors;
factorize(n, factors);
sort(factors.begin(), factors.end());
vector<pair<ll, int>> factorCounts;
for (ll f : factors) {
if (factorCounts.empty() || factorCounts.back().first != f)
factorCounts.push_back({f, 1});
else
factorCounts.back().second++;
}
vector<ll> divisors;
function<void(int, ll)> dfs = [&](int idx, ll current) {
if (idx == factorCounts.size()) {
divisors.push_back(current);
return;
}
ll prime = factorCounts[idx].first;
int exp = factorCounts[idx].second;
for (int i = 0; i <= exp; i++) {
dfs(idx + 1, current);
current *= prime;
}
};
dfs(0, 1);
sort(divisors.begin(), divisors.end());
return divisors;
}
struct Comb {
vector<mint> fact, ifact;
int MAX_COM;
Comb() {}
Comb(int n, int mod) {
MAX_COM = n;
init(mod, MAX_COM);
}
void init(long long MOD, long long MAX_COM) {
int n = MAX_COM;
assert(n < MOD);
fact = vector<mint>(n + 1);
ifact = vector<mint>(n + 1);
fact[0] = 1;
for (int i = 1; i <= n; ++i) fact[i] = fact[i - 1] * i;
ifact[n] = fact[n].inv();
for (int i = n; i >= 1; --i) ifact[i - 1] = ifact[i] * i;
}
mint operator()(long long n, long long k) {
if (k < 0 || k > n) return 0;
return fact[n] * ifact[k] * ifact[n - k];
}
};
Comb comb(5000010, 998244353);
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
int n = v.size();
rep(i, 0, n) { os << v[i] << " \n"[i == n - 1]; }
return os;
}
void solve() {
ll n, k;
cin >> n >> k;
vector<ll> a(n);
unordered_map<ll, int> ma, revd;
rep(i, 0, n) {
cin >> a[i];
a[i] = gcd(a[i], k);
ma[a[i]]++;
}
auto div = divisor(k);
rep(i, 0, div.size()) { revd[div[i]] = i; }
int d = div.size();
vector<mint> dp(d);
dp[0] = 1;
rep(i, 0, d) {
int cnt = ma[div[i]];
vector<mint> ndp(d);
rep(j, 0, d) {
if (dp[j] == 0) continue;
ll cur = div[j];
for (int c = 0; c <= cnt; c++) {
ndp[revd[cur]] += dp[j] * comb(cnt, c);
cur *= div[i];
cur = gcd(cur, k);
}
}
dp = ndp;
}
cout << dp[d - 1].val() << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(15);
solve();
}
SnowBeenDiding