結果
| 問題 | No.3785 Tree of Multiples |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-10-30 23:15:37 |
| 言語 | C++23 (gcc 15.3.0 + boost 1.92.0 + ACL) |
| 結果 |
AC
不安定
|
| 実行時間 | 1,127 ms / 6,000 ms |
| + 392µs | |
| コード長 | 4,997 bytes |
| 記録 | |
| コンパイル時間 | 6,542 ms |
| コンパイル使用メモリ | 404,252 KB |
| 実行使用メモリ | 64,740 KB |
| 最終ジャッジ日時 | 2026-10-30 23:16:02 |
| 合計ジャッジ時間 | 14,714 ms |
|
ジャッジサーバーID (参考情報) |
judge4_0 / judge1_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 16 |
ソースコード
/**
author: shobonvip
created: 2026.10.30 22:42:40
**/
#include<bits/stdc++.h>
using namespace std;
//* ATCODER
#include<atcoder/all>
using namespace atcoder;
typedef modint998244353 mint;
//*/
/* BOOST MULTIPRECISION
#include<boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
//*/
typedef long long ll;
#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) v.begin(), v.end()
template <typename T> bool chmin(T &a, const T &b) {
if (a <= b) return false;
a = b;
return true;
}
template <typename T> bool chmax(T &a, const T &b) {
if (a >= b) return false;
a = b;
return true;
}
template <typename T> T max(vector<T> &a){
assert(!a.empty());
T ret = a[0];
for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]);
return ret;
}
template <typename T> T min(vector<T> &a){
assert(!a.empty());
T ret = a[0];
for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]);
return ret;
}
template <typename T> T sum(vector<T> &a){
T ret = 0;
for (int i=0; i<(int)a.size(); i++) ret += a[i];
return ret;
}
//defmodfact
const int COMinitMAX = 999999;
mint fact[COMinitMAX+1], factinv[COMinitMAX+1];
void modfact(){
fact[0] = 1;
for (int i=1; i<=COMinitMAX; i++){
fact[i] = fact[i-1] * i;
}
factinv[COMinitMAX] = fact[COMinitMAX].inv();
for (int i=COMinitMAX-1; i>=0; i--){
factinv[i] = factinv[i+1] * (i+1);
}
}
mint cmb(int a, int b){
if (a<b || b<0) return mint(0);
return fact[a]*factinv[b]*factinv[a-b];
}
//--------
struct S {
vector<mint> v[4];
};
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// FPS game
modfact();
int n, m;
cin >> n >> m;
map<ll,ll> mp_a;
map<ll,ll> mp_b;
ll sum_a = 0, sum_b = 0;
rep(i,0,n) {
ll p,a; cin >> p >> a;
mp_a[p] = a;
sum_a += a;
}
rep(i,0,m) {
ll q,b; cin >> q >> b;
mp_b[q] = b;
sum_b += b;
}
// 倍数関係にある場合, だめだったw
bool a_div_b = true, b_div_a = true;
for (auto [p,a]: mp_a) {
if (!mp_b.contains(p) || mp_b[p] < a) {
a_div_b = false;
break;
}
}
for (auto [q,b]: mp_b) {
if (!mp_a.contains(q) || mp_a[q] < b) {
b_div_a = false;
break;
}
}
mint ans = 0;
if (a_div_b) {
mint tmp = fact[sum_a];
for (auto [p,a]: mp_a) {
tmp *= factinv[a];
tmp *= mint(p).pow(a);
}
tmp *= fact[sum_b-sum_a];
for (auto [q,b]: mp_b) {
if (mp_a.contains(q)) tmp *= factinv[b-mp_a[q]];
else tmp *= factinv[b];
}
ans += tmp;
}
if (b_div_a && !a_div_b) {
mint tmp = fact[sum_b];
for (auto [q,b]: mp_b) {
tmp *= factinv[b];
tmp *= mint(q).pow(b);
}
tmp *= fact[sum_a-sum_b];
for (auto [p,a]: mp_a) {
if (mp_b.contains(p)) tmp *= factinv[a-mp_b[p]];
else tmp *= factinv[a];
}
ans += tmp;
}
deque<S> f;
map<ll,ll> mp_gcd;
for (auto [p,a]: mp_a) {
if (mp_b.contains(p)) {
ll b = mp_b[p];
ll t = min(a, b);
mp_gcd[p] = min(a,b);
S tmp;
tmp.v[0].resize(t+1);
tmp.v[1].resize(t+1);
tmp.v[2].resize(t+1);
tmp.v[3].resize(t+1);
mint art=1;
rep(i,0,t+1) {
tmp.v[0][i] = art*factinv[i]*factinv[a-i]*factinv[b-i];
if (a-i>0) {
tmp.v[1][i] = art*factinv[i]*factinv[a-i-1]*factinv[b-i];
}
if (b-i>0) {
tmp.v[2][i] = art*factinv[i]*factinv[a-i]*factinv[b-i-1];
}
art*=p;
}
f.emplace_back(tmp);
} else {
S tmp;
tmp.v[0].resize(1);
tmp.v[1].resize(1);
tmp.v[2].resize(1);
tmp.v[3].resize(1);
tmp.v[0][0] = factinv[a];
tmp.v[1][0] = factinv[a] * a;
f.emplace_back(tmp);
}
}
for (auto [q,b]: mp_b) {
if (!mp_a.contains(q)) {
S tmp;
tmp.v[0].resize(1);
tmp.v[1].resize(1);
tmp.v[2].resize(1);
tmp.v[3].resize(1);
tmp.v[0][0] = factinv[b];
tmp.v[2][0] = factinv[b] * b;
f.emplace_back(tmp);
}
}
while(f.size()>1) {
S f1 = f.front(); f.pop_front();
S f2 = f.front(); f.pop_front();
vector<mint> g00 = convolution(f1.v[0], f2.v[0]);
vector<mint> g01 = convolution(f1.v[0], f2.v[1]);
vector<mint> g10 = convolution(f1.v[1], f2.v[0]);
vector<mint> g02 = convolution(f1.v[0], f2.v[2]);
vector<mint> g20 = convolution(f1.v[2], f2.v[0]);
vector<mint> g03 = convolution(f1.v[0], f2.v[3]);
vector<mint> g30 = convolution(f1.v[3], f2.v[0]);
vector<mint> g12 = convolution(f1.v[1], f2.v[2]);
vector<mint> g21 = convolution(f1.v[2], f2.v[1]);
int sz = (int)g00.size();
S tmp;
tmp.v[0].resize(sz);
tmp.v[1].resize(sz);
tmp.v[2].resize(sz);
tmp.v[3].resize(sz);
rep(i,0,sz) {
tmp.v[0][i] += g00[i];
tmp.v[1][i] += g01[i];
tmp.v[1][i] += g10[i];
tmp.v[2][i] += g02[i];
tmp.v[2][i] += g20[i];
tmp.v[3][i] += g03[i];
tmp.v[3][i] += g30[i];
tmp.v[3][i] += g12[i];
tmp.v[3][i] += g21[i];
}
f.emplace_back(tmp);
}
rep(i,0,(int)f[0].v[3].size()) {
if (sum_a-i-1 >= 0 && sum_b-i-1 >= 0) {
ans += f[0].v[3][i] * fact[i] * fact[sum_a-i-1] * fact[sum_b-i-1];
}
}
cout << ans.val() << endl;
}