結果
問題 | No.1075 木の上の山 |
ユーザー | QCFium |
提出日時 | 2020-06-05 21:42:39 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 63 ms / 2,000 ms |
コード長 | 4,073 bytes |
コンパイル時間 | 1,840 ms |
コンパイル使用メモリ | 183,784 KB |
実行使用メモリ | 23,424 KB |
最終ジャッジ日時 | 2024-05-09 20:31:59 |
合計ジャッジ時間 | 3,878 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,944 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 2 ms
6,940 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 3 ms
6,944 KB |
testcase_08 | AC | 2 ms
6,940 KB |
testcase_09 | AC | 2 ms
6,940 KB |
testcase_10 | AC | 3 ms
6,940 KB |
testcase_11 | AC | 3 ms
6,944 KB |
testcase_12 | AC | 3 ms
6,940 KB |
testcase_13 | AC | 3 ms
6,944 KB |
testcase_14 | AC | 3 ms
6,940 KB |
testcase_15 | AC | 4 ms
6,940 KB |
testcase_16 | AC | 3 ms
6,944 KB |
testcase_17 | AC | 51 ms
23,424 KB |
testcase_18 | AC | 63 ms
15,232 KB |
testcase_19 | AC | 48 ms
20,352 KB |
testcase_20 | AC | 63 ms
15,232 KB |
testcase_21 | AC | 49 ms
8,572 KB |
testcase_22 | AC | 45 ms
8,576 KB |
testcase_23 | AC | 47 ms
8,948 KB |
testcase_24 | AC | 48 ms
9,088 KB |
testcase_25 | AC | 46 ms
8,436 KB |
testcase_26 | AC | 63 ms
15,232 KB |
testcase_27 | AC | 56 ms
11,520 KB |
testcase_28 | AC | 48 ms
13,684 KB |
testcase_29 | AC | 56 ms
12,928 KB |
testcase_30 | AC | 61 ms
15,360 KB |
testcase_31 | AC | 56 ms
16,508 KB |
ソースコード
#include <bits/stdc++.h> int ri() { int n; scanf("%d", &n); return n; } #define MOD 1000000007 template<int mod> struct ModInt{ int x; ModInt():x(0){} ModInt(long long y):x(y>=0?y%mod:(mod-(-y)%mod)%mod){} ModInt &operator+=(const ModInt &p){ if((x+=p.x)>=mod)x-=mod; return *this; } ModInt &operator-=(const ModInt &p){ if((x+=mod-p.x)>=mod)x-=mod; return *this; } ModInt &operator*=(const ModInt &p){ x=(int)(1LL*x*p.x%mod); return *this; } ModInt &operator/=(const ModInt &p){ *this*=p.inverse(); return *this; } ModInt &operator^=(long long p){ ModInt res = 1; for (; p; p >>= 1) { if (p & 1) res *= *this; *this *= *this; } return *this = res; } ModInt operator-()const{return ModInt(-x);} ModInt operator+(const ModInt &p)const{return ModInt(*this)+=p;} ModInt operator-(const ModInt &p)const{return ModInt(*this)-=p;} ModInt operator*(const ModInt &p)const{return ModInt(*this)*=p;} ModInt operator/(const ModInt &p)const{return ModInt(*this)/=p;} ModInt operator^(long long p)const{return ModInt(*this)^=p;} bool operator==(const ModInt &p)const{return x==p.x;} bool operator!=(const ModInt &p)const{return x!=p.x;} explicit operator int() const { return x; } // added by QCFium ModInt operator=(const int p) {x = p; return ModInt(*this);} // added by QCFium ModInt inverse()const{ int a=x,b=mod,u=1,v=0,t; while(b>0){ t=a/b; a-=t*b; std::swap(a,b); u-=t*v; std::swap(u,v); } return ModInt(u); } friend std::ostream &operator<<(std::ostream &os,const ModInt<mod> &p){ return os<<p.x; } friend std::istream &operator>>(std::istream &is,ModInt<mod> &a){ long long x; is>>x; a=ModInt<mod>(x); return (is); } }; typedef ModInt<MOD> mint; struct MComb { std::vector<mint> fact; std::vector<mint> inv; MComb (int n) { // O(n + log(mod)) fact = std::vector<mint>(n + 1, 1); for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * mint(i); inv.resize(n + 1); inv[n] = fact[n] ^ (MOD - 2); for (int i = n; i--; ) inv[i] = inv[i + 1] * mint(i + 1); } mint ncr(int n, int r) { return fact[n] * inv[r] * inv[n - r]; } mint npr(int n, int r) { return fact[n] * inv[n - r]; } mint nhr(int n, int r) { assert(n + r - 1 < (int) fact.size()); return ncr(n + r - 1, r); } }; std::vector<std::vector<int> > hen; int k; std::vector<mint> merge(const std::vector<mint> &l, const std::vector<mint> &r) { int n = l.size(); std::vector<mint> res(n); mint suml = 0, sumr = 0; for (int i = 0; i < k; i++) { suml += l[i]; sumr += r[i]; res[i] += suml * r[i]; res[i] += sumr * l[i]; res[i] -= l[i] * r[i]; } return res; } mint res; std::vector<std::vector<mint> > subtree; void dfs0(int i, int prev) { if (prev != -1) hen[i].erase(std::find(hen[i].begin(), hen[i].end(), prev)); subtree[i].resize(k); subtree[i][0] = 1; for (auto j : hen[i]) { dfs0(j, i); subtree[i] = merge(subtree[i], subtree[j]); } for (int j = 0; j + 1 < k; j++) subtree[i][j + 1] += subtree[i][j]; } void dfs1(int i, int prev, const std::vector<mint> &par_dp) { int m = hen[i].size(); mint sumed = 0; for (int j = 0; j < k; j++) { res += subtree[i][j] * (prev == -1 ? 1 : sumed); if (prev != -1) sumed += par_dp[j]; } if (m) { std::vector<std::vector<mint> > left(m); std::vector<std::vector<mint> > right(m); std::vector<mint> tmp(k); tmp[0] = 1; left.front() = right.back() = tmp; for (int j = 0; j + 1 < m; j++) left[j + 1] = merge(left[j], subtree[hen[i][j]]); for (int j = m; --j; ) right[j - 1] = merge(right[j], subtree[hen[i][j]]); for (int j = 0; j < m; j++) { auto tmp = merge(merge(left[j], right[j]), par_dp); for (int l = 0; l + 1 < k; l++) tmp[l + 1] += tmp[l]; dfs1(hen[i][j], i, tmp); } } } int main() { int n = ri(); k = ri(); hen.resize(n); for (int i = 1; i < n; i++) { int a = ri() - 1; int b = ri() - 1; hen[a].push_back(b); hen[b].push_back(a); } subtree.resize(n); dfs0(0, -1); std::vector<mint> tmp(k); tmp[0] = 1; dfs1(0, -1, tmp); std::cout << res << std::endl; return 0; }