Submission #1213407

#TimeUsernameProblemLanguageResultExecution timeMemory
1213407Zero_OPStar Trek (CEOI20_startrek)C++20
45 / 100
39 ms17476 KiB
#include <bits/stdc++.h> using namespace std; //loops (warning : long long) #define FOR(i, l, r) for(int i = (l); i < (r); ++i) #define ROF(i, r, l) for(int i = (r - 1); i >= l; --i) #define rep(i, l, r) for(int i = (l); i < (r); ++i) //pairs, tuples #define mp make_pair #define mt make_tuple #define ff first #define ss second //vectors #define all(v) begin(v), end(v) #define rall(v) rbegin(v), rend(v) #define pb push_back #define eb emplace_back #define sum_of(v) accumulate(all(v), 0ll) #define sz(v) (int)v.size() #define compact(v) v.erase(unique(all(v)), end(v)) //binary search #define lwb lower_bound #define upb upper_bound //other stuffs #define dbg(x) "[" #x " = " << (x) << "]" #define file(task) if(fopen(task".inp", "r")){ freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); } template<typename T> bool minimize(T& a, const T& b){ if(a > b) return a = b, true; return false; } template<typename T> bool maximize(T& a, const T& b){ if(a < b) return a = b, true; return false; } using ll = long long; using ull = unsigned long long; using ld = long double; using db = double; using pi = pair<int, int>; using pl = pair<ll, ll>; using vi = vector<int>; using vb = vector<bool>; using vl = vector<ll>; using vpi = vector<pi>; using vpl = vector<pl>; mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); const int MAX = 1e5 + 5; const int mod = 1e9 + 7; template<typename T> T ext_gcd(T a, T b, T& x, T& y){ if(b == 0){ x = 1, y = 0; return a; } T x1, y1, d = ext_gcd(b, a % b, x1, y1); x = y1; y = x1 - y1 * (a / b); return d; } struct mint{ int v; mint() : v(0) {} mint(int v) : v(v) { if(v < 0) v += mod; if(v >= mod) v -= mod; } friend bool operator == (const mint& a, const mint& b){ return a.v == b.v; } friend bool operator != (const mint& a, const mint& b){ return a.v != b.v; } mint& operator += (const mint& o){ v += o.v; if(v >= mod) v -= mod; return *this; } mint& operator -= (const mint& o){ v -= o.v; if(v < 0) v += mod; return *this; } mint& operator *= (const mint& o){ v = 1LL * v * o.v % mod; return *this; } mint power(ll n) const{ mint result(1), base = *this; for(; n > 0; n >>= 1, base *= base){ if(n & 1) result *= base; } return result; } mint inv() const{ return power(mod - 2); //note when mod is non-prime, result = power(\varphi(mod) - 1) } mint& operator /= (const mint& o){ return *this *= o.inv(); } friend mint operator - (const mint& a){ return mint(0) - a; } friend mint operator + (mint a, const mint& b){ return a += b; } friend mint operator - (mint a, const mint& b){ return a -= b; } friend mint operator * (mint a, const mint& b){ return a *= b; } friend mint operator / (mint a, const mint& b){ return a /= b; } friend ostream& operator << (ostream& out, const mint& v){ return out << v.v; } }; template<typename T> struct Matrix{ vector<vector<T>> mat; int row() const { return sz(mat); } int col() const { return sz(mat[0]); } auto & operator [](int i){ return mat[i]; } const auto & operator [](int i) const { return mat[i]; } Matrix() = default; Matrix(int n, int m, T init) : mat(n, vector<T>(m, init)) {} Matrix(const vector<vector<T>>& ar) : mat(ar) {} friend ostream& operator << (ostream& out, const Matrix& d){ for(auto x : d.mat){ for(auto y : x) out << y << ' '; out << '\n'; } return out; } static Matrix identity(int n){ Matrix a = Matrix(n, n, T(0)); while(n--) a[n][n] = T(1); return a; } friend Matrix operator * (const Matrix& a, const Matrix& b){ assert(a.col() == b.row()); Matrix result(a.row(), b.col(), T(0)); rep(i, 0, a.row()){ rep(j, 0, b.col()){ rep(k, 0, a.col()){ result[i][j] += a[i][k] * b[k][j]; } } } return result; } Matrix& operator *= (const Matrix& b){ return (*this) = (*this) * b; } Matrix power(long long n){ assert(row() == col()); Matrix base = *this, ans = identity(row()); for(; n > 0; n >>= 1, base *= base){ if(n & 1) ans *= base; } return ans; } }; int N; ll D; vi adj[MAX]; //Root at 1 int state[MAX], cnt[MAX]; //Reroot int root_state[MAX], root_cnt[MAX], up_state[MAX], up_cnt[MAX]; void dfs(int u){ cnt[u] = 1; for(auto v : adj[u]){ adj[v].erase(find(all(adj[v]), u)); dfs(v); if(!state[v]){ if(!state[u]){ cnt[u] = cnt[v]; state[u] = 1; } else cnt[u] = 0; } else{ if(!state[u]) cnt[u] += cnt[v]; } } } void dfs_reroot(int u){ int n0 = 0, n1 = 0, s0 = 0, s1 = 0; for(auto v : adj[u]){ if(!state[v]) ++n0, s0 += cnt[v]; else ++n1, s1 += cnt[v]; } if(up_state[u] == 0) ++n0, s0 += up_cnt[u]; if(up_state[u] == 1) ++n1, s1 += up_cnt[u]; for(auto v : adj[u]){ if(!state[v]) --n0, s0 -= cnt[v]; else --n1, s1 -= cnt[v]; int subtree_u_state = (n0 > 0 ? 1 : 0); int subtree_u_cnt = (subtree_u_state == 0 ? s1 : (n0 == 1 ? s0 : 0)); up_state[v] = subtree_u_state; up_cnt[v] = subtree_u_cnt; if(!state[v]){ if(subtree_u_state == 0){ root_state[v] = 1; root_cnt[v] = subtree_u_cnt; } else{ root_state[v] = 0; root_cnt[v] = subtree_u_cnt + cnt[v]; } } else{ if(subtree_u_state == 0){ root_state[v] = 1; root_cnt[v] = 0; } else{ root_state[v] = 1; root_cnt[v] = cnt[v]; } } dfs_reroot(v); if(!state[v]) ++n0, s0 += cnt[v]; else ++n1, s1 += cnt[v]; } } void testcase(int ntestcase){ cin >> N >> D; for(int i = 1; i < N; ++i){ int u, v; cin >> u >> v; adj[u].pb(v); adj[v].pb(u); } dfs(1); up_state[1] = -1; root_state[1] = state[1]; root_cnt[1] = cnt[1]; dfs_reroot(1); // for(int i = 1; i <= N; ++i){ // cout << root_state[i]; // } // cout << '\n'; int L = 0, W = 0; mint a = 0, b = 0, c = 0, d = 0; for(int i = 1; i <= N; ++i){ L += (root_state[i] == 0); W += (root_state[i] == 1); if(root_state[i] == 0){ a += root_cnt[i]; b += N - root_cnt[i]; c += N; } else{ d += N; } } if(D == 1){ if(state[1] == 0){ cout << (1LL * cnt[1] * L) % mod << '\n'; } else{ cout << (1LL * N * N - 1LL * cnt[1] * L) % mod << '\n'; } } else{ mint n2(1LL * N * N % mod); Matrix<mint> trans(2, 2, 0); trans[0][0] = b; trans[0][1] = c; trans[1][0] = a; trans[1][1] = d; // cout << trans << '\n'; trans.power(D); // cout << trans << '\n'; // cout << trans[0][0] << ' ' << L << '\n'; // cout << trans[0][1] << ' ' << W << '\n'; mint n_losing = trans[0][0] * mint(L) + trans[0][1] * mint(W); if(state[1] == 0){ cout << n_losing * mint(cnt[1]) << '\n'; } else{ mint all = n2.power(D); cout << (all - (n_losing) * mint(cnt[1])) << '\n'; } } } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); #ifdef LOCAL freopen("task.inp", "r", stdin); freopen("task.out", "w", stdout); #endif // LOCAL int T = 1; // cin >> T; FOR(i, 0, T) testcase(i); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...