QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#311006#4781. 完美的集合hos_lyric#19 13ms4128kbC++1415.7kb2024-01-21 20:50:042024-07-04 03:20:27

Judging History

你现在查看的是最新测评结果

  • [2024-07-04 03:20:27]
  • 评测
  • 测评结果:19
  • 用时:13ms
  • 内存:4128kb
  • [2024-01-21 20:50:04]
  • 提交

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;
}

Details

Tip: Click on the bar to expand more detailed information

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%