QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#311006 | #4781. 完美的集合 | hos_lyric# | 19 | 13ms | 4128kb | C++14 | 15.7kb | 2024-01-21 20:50:04 | 2024-07-04 03:20:27 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
////////////////////////////////////////////////////////////////////////////////
template <unsigned long long M_> struct ModLong {
static constexpr unsigned long long M = M_;
static constexpr long double INV_M = 1.0L / M;
unsigned long long x;
ModLong() : x(0ULL) {}
ModLong(unsigned x_) : x(x_ % M) {}
ModLong(unsigned long long x_) : x(x_ % M) {}
ModLong(int x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModLong(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModLong &operator+=(const ModLong &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
ModLong &operator-=(const ModLong &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
ModLong &operator*=(const ModLong &a) {
// https://github.com/kth-competitive-programming/kactl/blob/main/doc/modmul-proof.pdf
// This works at least for M < 2^62, assuming the usual 80-bit long double.
const long long y = x * a.x - M * static_cast<unsigned long long>(INV_M * x * a.x);
x = (y < 0LL) ? (y + M) : (y >= static_cast<long long>(M)) ? (y - M) : y;
return *this;
}
ModLong &operator/=(const ModLong &a) { return (*this *= a.inv()); }
ModLong pow(long long e) const {
if (e < 0) return inv().pow(-e);
ModLong a = *this, b = 1ULL; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
}
ModLong inv() const {
unsigned long long a = M, b = x; long long y = 0, z = 1;
for (; b; ) { const unsigned long long q = a / b; const unsigned long long c = a - q * b; a = b; b = c; const long long w = y - static_cast<long long>(q) * z; y = z; z = w; }
assert(a == 1ULL); return ModLong(y);
}
ModLong operator+() const { return *this; }
ModLong operator-() const { ModLong a; a.x = x ? (M - x) : 0ULL; return a; }
ModLong operator+(const ModLong &a) const { return (ModLong(*this) += a); }
ModLong operator-(const ModLong &a) const { return (ModLong(*this) -= a); }
ModLong operator*(const ModLong &a) const { return (ModLong(*this) *= a); }
ModLong operator/(const ModLong &a) const { return (ModLong(*this) /= a); }
template <class T> friend ModLong operator+(T a, const ModLong &b) { return (ModLong(a) += b); }
template <class T> friend ModLong operator-(T a, const ModLong &b) { return (ModLong(a) -= b); }
template <class T> friend ModLong operator*(T a, const ModLong &b) { return (ModLong(a) *= b); }
template <class T> friend ModLong operator/(T a, const ModLong &b) { return (ModLong(a) /= b); }
explicit operator bool() const { return x; }
bool operator==(const ModLong &a) const { return (x == a.x); }
bool operator!=(const ModLong &a) const { return (x != a.x); }
friend std::ostream &operator<<(std::ostream &os, const ModLong &a) { return os << a.x; }
};
////////////////////////////////////////////////////////////////////////////////
using ModInt = ModLong<11920928955078125>;
struct BinomPE {
static constexpr int p = 5;
static constexpr int e = 23;
static constexpr unsigned long long M = 11920928955078125;
ModInt mod(int x_) const {
return x_;
}
ModInt mod(long long x_) const {
return x_;
}
ModInt add(ModInt a, ModInt b) const {
return a + b;
}
ModInt mul(ModInt a, ModInt b) const {
return a * b;
}
ModInt pow(ModInt a, long long e_) const {
return a.pow(e_);
}
ModInt inv(ModInt a) const {
return a.inv();
}
// pp[i] = p^i
vector<unsigned long long> pp;
// period mod p^e of (-1 mod p)
unsigned long long period;
// s1[n][k] = |s(n+1, k+1)| (in particular, s1[p-1][0] = (p-1)!)
vector<vector<ModInt>> s1;
// fs[u] = \prod[0<=i<u] range(i, p-1): poly in u of deg=2e-2
int deg;
vector<ModInt> fs;
// valFac[i] = v_p(i!), invFac[i] = (i! / p^(v_p(i!)))^-1
vector<int> valFac;
vector<ModInt> invFac;
BinomPE() {
assert(p >= 2); assert(e >= 1);
pp.resize(e + 1);
pp[0] = 1;
for (int i = 1; i <= e; ++i) pp[i] = pp[i - 1] * p;
// setM(pp[e]);
period = ((p == 2 && e >= 3) ? 1 : 2) * pp[e - 1];
s1.assign(p, vector<ModInt>(min(p, e), ModInt{0U}));
s1[0][0] = ModInt{1U};
for (int n = 1; n < p; ++n) {
s1[n][0] = mul(mod(n), s1[n - 1][0]);
for (int k = 1; k < min(p, e); ++k) s1[n][k] = add(s1[n - 1][k - 1], mul(mod(n), s1[n - 1][k]));
}
const ModInt invFac1 = inv(s1[p - 1][0]);
deg = 2 * e - 2;
fs.resize(deg + 1);
fs[0] = ModInt{1U};
for (int u = 0; u < deg; ++u) fs[u + 1] = mul(fs[u], mul(invFac1, range(u, p - 1)));
valFac.resize(deg + 1);
invFac.resize(deg + 1);
valFac[0] = 0;
invFac[0] = ModInt{1U};
ModInt prod{1U};
for (int i = 1; i <= deg; ++i) {
int ii = i, val = 0;
for (; ii % p == 0; ii /= p, ++val) {}
valFac[i] = valFac[i - 1] + val;
prod = mul(prod, invFac[i - 1] = mod(ii));
}
invFac[deg] = inv(prod);
for (int i = deg; i >= 1; --i) invFac[i - 1] = mul(invFac[i - 1], invFac[i]);
}
// v_p(n!)
long long valuationFac(long long n) const {
long long ret = 0;
for (; n /= p; ret += n) {}
return ret;
}
// (u p + 1) ... (u p + v)
ModInt range(long long u, int v) const {
const ModInt up = mod(static_cast<long long>(u) * p);
ModInt ret{0U};
for (int k = min(p, e); --k >= 0; ) ret = add(mul(ret, up), s1[v][k]);
return ret;
}
// (\prod[1<=i<=up+v, p!|i] i) / (p-1)!^u
ModInt facSkipped(long long u, int v) const {
const ModInt tail = range(u, v);
if (u <= deg) return mul(fs[u], tail);
vector<pair<int, ModInt>> works(deg + 1);
vector<int> valSuf(deg + 2);
vector<ModInt> prodSuf(deg + 2);
valSuf[deg + 1] = 0;
prodSuf[deg + 1] = ModInt{1U};
for (int i = deg; i >= 0; --i) {
long long uu = u - i;
int val = 0;
for (; uu % p == 0; uu /= p) ++val;
works[i] = make_pair(val, mod(uu));
valSuf[i] = val + valSuf[i + 1];
prodSuf[i] = mul(works[i].second, prodSuf[i + 1]);
}
int valPre = 0;
ModInt prodPre = ModInt{1U};
ModInt sum = ModInt{0U};
for (int i = 0; i <= deg; ++i) {
// (u-0)...(u-(i-1))(u-(i+1))...(u-deg) / (i-0)...(i-(i-1))(i-(i+1))...(i-deg)
const int val = valPre + valSuf[i + 1] - valFac[i] - valFac[deg - i];
if (val < e) {
sum = add(sum, mul(mul(
mul(ModInt{pp[val]}, mul(prodPre, prodSuf[i + 1])),
mul(invFac[i], mul(invFac[deg - i], mod(((deg - i) & 1) ? -1 : +1)))
), fs[i]));
}
valPre += works[i].first;
prodPre = mul(prodPre, works[i].second);
}
return mul(sum, tail);
}
// n! / p^(v_p(n!))
ModInt facP(long long n) const {
long long sum = 0;
ModInt prod{1U};
for (; n; ) {
const long long q = n / p, v = n % p;
const long long u = q % period;
sum += u;
prod = mul(prod, facSkipped(u, v));
n = q;
}
return mul(pow(s1[p - 1][0], sum % period), prod);
}
// binom(n, k)
ModInt operator()(long long n, long long k) const {
if (n < 0) {
if (k >= 0) {
return mul(mod((k & 1) ? -1 : +1), (*this)(-n + k - 1, k));
} else if (n - k >= 0) {
return mul(mod(((n - k) & 1) ? -1 : +1), (*this)(-k - 1, n - k));
} else {
return ModInt{0U};
}
} else {
if (0 <= k && k <= n) {
const long long val = valuationFac(n) - valuationFac(k) - valuationFac(n - k);
if (val >= e) return ModInt{0U};
return mul(ModInt{pp[val]}, mul(facP(n), inv(mul(facP(k), facP(n - k)))));
} else {
return ModInt{0U};
}
}
}
} binom;
constexpr Int INFLL = 1001001001001001001LL;
int N, M, K;
Int L;
vector<int> W;
vector<Int> V;
vector<int> A, B, C;
vector<vector<int>> G;
namespace brute {
ModInt run() {
vector<int> adj(N, 0);
for (int i = 0; i < N - 1; ++i) {
adj[A[i]] |= 1 << B[i];
adj[B[i]] |= 1 << A[i];
}
vector<int> WSum(1 << N, 0);
vector<Int> VSum(1 << N, 0);
vector<int> es(1 << N, 0);
for (int u = 0; u < N; ++u) for (int p = 0; p < 1 << u; ++p) {
WSum[p | 1 << u] = WSum[p] + W[u];
VSum[p | 1 << u] = VSum[p] + V[u];
es[p | 1 << u] = es[p] + __builtin_popcount(p & adj[u]);
}
Int maxV = -1;
vector<int> ps;
for (int p = 0; p < 1 << N; ++p) if (WSum[p] <= M && es[p] == __builtin_popcount(p) - 1) {
if (chmax(maxV, VSum[p])) ps.clear();
if (maxV == VSum[p]) ps.push_back(p);
}
cerr<<"ps = "<<ps<<endl;
vector<vector<int>> dist(N, vector<int>(N, 1001001001));
for (int u = 0; u < N; ++u) dist[u][u] = 0;
for (int i = 0; i < N - 1; ++i) dist[A[i]][B[i]] = dist[B[i]][A[i]] = C[i];
for (int w = 0; w < N; ++w) for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) chmin(dist[u][v], dist[u][w] + dist[w][v]);
ModInt ans = 0;
for (int u = 0; u < N; ++u) {
Int way = 0;
for (const int p : ps) if (p >> u & 1) {
bool ok = true;
for (int v = 0; v < N; ++v) if (p >> v & 1) {
ok = ok && (dist[u][v] * V[v] <= L);
}
if (ok) ++way;
}
cerr<<COLOR("91")<<u<<": "<<way<<COLOR()<<endl;
ans += binom(way, K);
}
for (int i = 0; i < N - 1; ++i) {
Int way = 0;
for (const int p : ps) if ((p >> A[i] & 1) && (p >> B[i] & 1)) {
bool ok = true;
for (int v = 0; v < N; ++v) if (p >> v & 1) {
ok = ok && (max(dist[A[i]][v], dist[B[i]][v]) * V[v] <= L);
}
if (ok) ++way;
}
cerr<<COLOR("94")<<A[i]<<" "<<B[i]<<": "<<way<<COLOR()<<endl;
ans -= binom(way, K);
}
return ans;
}
} // brute
namespace sub3 {
ModInt run() {
Int maxV = -1;
if (M == 1) {
vector<int> us;
for (int u = 0; u < N; ++u) {
if (chmax(maxV, V[u])) us.clear();
if (maxV == V[u]) us.push_back(u);
}
return (int)us.size() * binom(1, K);
}
vector<int> is;
for (int i = 0; i < N - 1; ++i) {
if (chmax(maxV, V[A[i]] + V[B[i]])) is.clear();
if (maxV == V[A[i]] + V[B[i]]) is.push_back(i);
}
cerr<<"is = "<<is<<endl;
ModInt ans = 0;
for (int u = 0; u < N; ++u) {
Int way = 0;
for (const int i : is) if (A[i] == u || B[i] == u) {
const int v = A[i] ^ B[i] ^ u;
if (C[i] * V[v] <= L) ++way;
}
cerr<<COLOR("91")<<u<<": "<<way<<COLOR()<<endl;
ans += binom(way, K);
}
for (const int i : is) {
Int way = 0;
if (C[i] * max(V[A[i]], V[B[i]]) <= L) ++way;
cerr<<COLOR("94")<<A[i]<<" "<<B[i]<<": "<<way<<COLOR()<<endl;
ans -= binom(way, K);
}
return ans;
}
} // brute
namespace fast {
vector<int> sz;
vector<vector<int>> g;
void dfsHld(int u, int p) {
int mx = -1;
int im = -1;
for (const int i : G[u]) {
const int v = A[i] ^ B[i] ^ u;
if (p != v) {
dfsHld(v, u);
sz[u] += sz[v];
if (chmax(mx, sz[v])) im = i;
}
}
if (~im) {
g[u].push_back(im);
for (const int i : G[u]) if (im != i) {
const int v = A[i] ^ B[i] ^ u;
if (p != v) g[u].push_back(i);
}
}
}
// (max value, way)
using Pair = pair<Int, Int>;
constexpr Pair ZERO(-INFLL, 0);
vector<Pair> INI;
Pair operator+(const Pair &a, const Pair &b) {
if (a.first > b.first) return a;
if (a.first < b.first) return b;
return Pair(a.first, a.second + b.second);
}
// merge assuming (root is not used, root is used)
pair<vector<Pair>, vector<Pair>> dfs(
int phase, int u, int d, const vector<Pair> &fs) {
// cerr<<"[dfs] "<<phase<<" "<<u<<" "<<d<<" "<<fs<<endl;
pair<vector<Pair>, vector<Pair>> ret;
if (g[u].size()) {
for (const int i : g[u]) {
const int v = A[i] ^ B[i] ^ u;
if (i == g[u][0]) {
ret = dfs(phase, v, d + C[i], fs);
} else {
// ret.first = dfs(phase, v, d + C[i], ret.first ).first ;
ret.first = INI;
ret.second = dfs(phase, v, d + C[i], ret.second).second;
}
}
} else {
ret.first = ret.second = fs;
}
if (phase == 0 || d * V[u] <= L) {
for (int x = M; x >= 0; --x) {
if (x >= W[u]) {
Pair t = ret.second[x - W[u]];
t.first += V[u];
ret.second[x] = ret.first[x] + t;
} else {
ret.second[x] = ret.first[x];
}
}
} else {
ret.second = ret.first;
}
// cerr<<COLOR("92")<<"[dfs] "<<phase<<" "<<u<<" "<<d<<" "<<fs<<" = "<<ret<<COLOR()<<endl;
return ret;
}
vector<Pair> calc(int phase, int u, int p, int d0) {
sz.assign(N, 1);
g.assign(N, {});
dfsHld(u, p);
// cerr<<u<<" "<<p<<": g = "<<g<<endl;
return dfs(phase, u, d0, INI).second;
}
ModInt run() {
INI.assign(M + 1, ZERO);
INI[0] = Pair(0, 1);
Int maxV = -1;
for (int u = 0; u < N; ++u) {
const auto res = calc(0, u, -1, 0);
// cerr<<u<<": "<<res<<endl;
for (int m = 0; m <= M; ++m) {
if (m) chmax(maxV, res[m].first);
}
}
cerr<<"maxV = "<<maxV<<endl;
ModInt ans = 0;
for (int u = 0; u < N; ++u) {
const auto res = calc(1, u, -1, 0);
Int way = 0;
for (int m = 0; m <= M; ++m) if (m) if (maxV == res[m].first) way += res[m].second;
cerr<<COLOR("91")<<u<<": "<<way<<" "<<binom(way,K)<<COLOR()<<endl;
ans += binom(way, K);
}
for (int i = 0; i < N - 1; ++i) {
const auto resA = calc(1, A[i], B[i], C[i]);
const auto resB = calc(1, B[i], A[i], C[i]);
// cerr<<A[i]<<" "<<B[i]<<": "<<resA<<" "<<resB<<endl;
Int way = 0;
{
Pair sum = ZERO;
for (int m = M; m >= 0; --m) {
if (M - m) sum = sum + resA[M - m];
if (m) if (maxV == sum.first + resB[m].first) {
way += sum.second * resB[m].second;
}
}
}
cerr<<COLOR("94")<<A[i]<<" "<<B[i]<<": "<<way<<" "<<binom(way,K)<<COLOR()<<endl;
ans -= binom(way, K);
}
return ans;
}
} // fast
int main() {
for (; ~scanf("%d%d%d%lld", &N, &M, &K, &L); ) {
W.resize(N);
for (int u = 0; u < N; ++u) {
scanf("%d", &W[u]);
chmin(W[u], M + 1);
}
V.resize(N);
for (int u = 0; u < N; ++u) {
scanf("%lld", &V[u]);
}
A.resize(N - 1);
B.resize(N - 1);
C.resize(N - 1);
for (int i = 0; i < N - 1; ++i) {
scanf("%d%d%d", &A[i], &B[i], &C[i]);
--A[i];
--B[i];
}
G.assign(N, {});
for (int i = 0; i < N - 1; ++i) {
G[A[i]].push_back(i);
G[B[i]].push_back(i);
}
ModInt ans = 0;
ans = fast::run();
printf("%llu\n", ans.x);
#ifdef LOCAL
if(N<=20){
const ModInt brt=brute::run();
cerr<<"brt = "<<brt<<endl;
assert(brt==ans);
}
#endif
}
return 0;
}
详细
Subtask #1:
score: 0
Wrong Answer
Test #1:
score: 0
Wrong Answer
time: 1ms
memory: 4128kb
input:
16 109 1 4025082 46 68 46 1 46 67 111 1 156 1 45 45 1 45 45 45 8525 12789 8526 0 8526 12788 954 0 6 0 8525 8526 0 8525 8526 8526 1 2 290 1 3 188 1 4 420 1 5 6 2 6 29 1 7 643 1 8 461 4 9 468 1 10 228 5 11 428 2 12 71 4 13 290 1 14 957 2 15 955 4 16 549
output:
21
result:
wrong answer 1st numbers differ - expected: '25', found: '21'
Subtask #2:
score: 0
Wrong Answer
Test #13:
score: 0
Wrong Answer
time: 13ms
memory: 3864kb
input:
40 816 1 285 46 124 125 137 90 33 15 73 67 41 134 106 3 163 152 151 14 77 157 82 40 9 151 148 60 60 163 71 40 134 152 145 70 59 26 64 94 38 158 57 2 2 1 1 1 1 3 3 1 1 3 3 1 3 1 3 2 1 3 3 1 1 2 2 3 2 1 2 1 2 2 1 3 3 3 1 1 1 3 3 1 2 20 1 3 26 2 4 14 3 5 25 1 6 17 4 7 49 1 8 37 1 9 50 2 10 52 4 11 55 2...
output:
2
result:
wrong answer 1st numbers differ - expected: '3', found: '2'
Subtask #3:
score: 19
Accepted
Test #17:
score: 19
Accepted
time: 0ms
memory: 4108kb
input:
60 2 14 266401688520 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 712303980 712303980 712303979 712303980 712303980 712303980 712303980 712303980 712303980 712303980 712303980 712303980 712303980 712303980 712303980 712303980...
output:
120
result:
ok 1 number(s): "120"
Test #18:
score: 0
Accepted
time: 0ms
memory: 3824kb
input:
56 2 7 534719494983 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 649719921 649719921 649719920 649719921 649719920 649719921 649719921 649719921 649719921 649719921 649719921 649719921 649719921 649719921 649719921 649719921 64971992...
output:
12620256
result:
ok 1 number(s): "12620256"
Test #19:
score: 0
Accepted
time: 2ms
memory: 4116kb
input:
59 2 18 362091866924 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 542053693 542053693 542053693 542053693 542053693 542053693 542053693 542053693 542053693 542053693 542053693 542053692 542053693 542053693 542053693 542053693 5...
output:
1037158320
result:
ok 1 number(s): "1037158320"
Subtask #4:
score: 0
Skipped
Dependency #1:
0%
Subtask #5:
score: 0
Skipped
Dependency #2:
0%
Subtask #6:
score: 0
Skipped
Dependency #1:
0%