結果
| 問題 |
No.2360 Path to Integer
|
| コンテスト | |
| ユーザー |
aoblue2547
|
| 提出日時 | 2024-02-26 00:10:12 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 103 ms / 2,500 ms |
| コード長 | 3,845 bytes |
| コンパイル時間 | 4,876 ms |
| コンパイル使用メモリ | 319,944 KB |
| 実行使用メモリ | 38,144 KB |
| 最終ジャッジ日時 | 2024-09-29 11:28:46 |
| 合計ジャッジ時間 | 6,922 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 15 |
ソースコード
//テンプレート
//Visual Studio用
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
template<class T> bool chmin(T& a, T b) { return a > b ? a = b, true : false; }
template<class T> bool chmax(T& a, T b) { return a < b ? a = b, true : false; }
template<class T>istream& operator>>(istream& is, vector<T>& v) { for (auto& e : v)is >> e; return is; }
template<class T>ostream& operator<<(ostream& os, vector<T>& v) { for (auto& e : v)os << e << " "; return os; }
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
template<class T = ll> struct Edge {
int to;
T weight;
Edge(int t, T w) :to(t), weight(w) {}
bool operator==(Edge e) {
return this->to == e.to and this->weight == e.weight;
}
bool operator<(Edge e) {
if (this->to < e.to) {
return this->weight <= e.weight;
}
else return false;
}
};
template<class T = ll> class Graph {
using graph_ = vector<vector<Edge<T>>>;
graph_ g;
public:
Graph(int n) :g(n) {}
graph_::iterator begin() { return g.begin(); }
graph_::const_iterator begin() const { return g.begin(); }
graph_::iterator end() { return g.end(); }
graph_::const_iterator end() const { return g.end(); }
vector<Edge<T>>& operator [](int v) {
return g[v];
}
const graph_& data() { return g; }
void add(int u, int v, T w = 1) {
g[u].emplace_back(Edge<T>{ v, w });
}
void wadd(int u, int v, T w = 1) {
add(u, v, w);
add(v, u, w);
}
void add(int u, Edge<T> edge) {
g[u].emplace_back(edge);
}
};
//Atcoder Library
/**/
#include <atcoder/all>
using namespace atcoder;
using mint = modint998244353;
//using mint = modint1000000007;
//using mint = dynamic_modint<0>;
//using mint = modint;
//mint::set_mod();
istream& operator>>(istream& is, mint& x) { ll r; cin >> r; x = r; return is; }
ostream& operator<<(ostream& os, mint& x) { cout << x.val(); return os; }
/**/
#define SHOW(n) cerr << #n << " = " << n << endl;
/*
ここまでテンプレート
*/
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<mint> a(n, 0);
vector<int> siz(n);
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
siz[i] = s.size();
for (int j = 0; j < s.size(); ++j) {
if (j != 0) a[i] *= 10;
a[i] += s[j] - '0';
}
}
Graph g(n);
for (int i = 0; i < n - 1; ++i) {
int a, b;
cin >> a >> b;
--a; --b;
g.wadd(a, b);
}
vector<mint> dp(n, 0);
vector<vector<mint>> dp_aux(n);
vector<int> bubun(n, 0);
auto dfs1 = [&](auto&& f, int v, int prev)->mint {
mint res = 0;
const int deg = g[v].size();
dp_aux[v].resize(deg);
for (int i = 0; i < deg; ++i) {
int s = g[v][i].to;
if (s == prev)continue;
f(f, s, v);
dp_aux[v][i] = dp[s];
res = res + dp_aux[v][i];
bubun[v] += bubun[s];
}
bubun[v] += 1;
res *= mint(10).pow(siz[v]);
res += a[v] * (bubun[v]);
return dp[v] = res;
};
dfs1(dfs1, 0, -1);
auto dfs2 = [&](auto&& f, int v, int prev, mint pval, int subsiz)->void {
const int deg = g[v].size();
for (int i = 0; i < deg; ++i) {
if (g[v][i].to == prev)dp_aux[v][i] = pval;
}
// 左右からdp_aux[v][i]の累積和を取る
vector<mint> accl(deg + 1, 0), accr(deg + 1, 0);
for (int i = 0; i < deg; ++i) {
accl[i + 1] = accl[i] + dp_aux[v][i];
}
for (int i = deg - 1; i >= 0; --i) {
accr[i] = accr[i + 1] + dp_aux[v][i];
}
dp[v] = accl[deg];
dp[v] *= mint(10).pow(siz[v]);
dp[v] += a[v] * (subsiz + bubun[v]);
// 行きがけ順で探索する
for (int i = 0; i < deg; ++i) {
int s = g[v][i].to;
if (s == prev)continue;
mint val = accl[i] + accr[i + 1];
val *= mint(10).pow(siz[v]);
val += a[v] * (n - bubun[s]);
f(f, s, v, val, n - bubun[s]);
}
};
dfs2(dfs2, 0, -1, 0, 0);
mint res = reduce(dp.begin(), dp.end());
cout << res.val() << endl;
return 0;
}
aoblue2547