Submission #1196105

#TimeUsernameProblemLanguageResultExecution timeMemory
1196105Zbyszek99Star Trek (CEOI20_startrek)C++20
100 / 100
100 ms34832 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define ll long long #define ld long double #define ull unsigned long long #define ff first #define ss second #define pii pair<int,int> #define pll pair<long long, long long> #define vi vector<int> #define vl vector<long long> #define pb push_back #define rep(i, b) for(int i = 0; i < (b); ++i) #define rep2(i,a,b) for(int i = a; i <= (b); ++i) #define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c) #define count_bits(x) __builtin_popcountll((x)) #define all(x) (x).begin(),(x).end() #define siz(x) (int)(x).size() #define forall(it,x) for(auto& it:(x)) using namespace __gnu_pbds; using namespace std; typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set; //mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());} //ll los(ll a, ll b) {return a + (mt() % (b-a+1));} const int INF = 1e9+50; const ll INF_L = 1e18+40; const ll MOD = 1e9+7; struct node { ll dp[2][2]; int sub_siz = 0; bool is_win = 0; }; struct dp_ { ll dp[2][2]; dp_() { rep(d1,2) rep(d2,2) dp[d1][d2] = 0; } dp_ operator+(const dp_& other) { dp_ res; res.dp[0][0] = other.dp[0][0] * dp[0][0] + other.dp[1][0] * dp[0][1]; res.dp[0][1] = other.dp[0][1] * dp[0][0] + other.dp[1][1] * dp[0][1]; res.dp[1][0] = other.dp[0][0] * dp[1][0] + other.dp[1][0] * dp[1][1]; res.dp[1][1] = other.dp[0][1] * dp[1][0] + other.dp[1][1] * dp[1][1]; rep(d1,2) rep(d2,2) res.dp[d1][d2] %= MOD; return res; } }; vi graph[100001]; node dp_node[100001]; dp_ beg_tree; dp_ mid_tree; dp_ end_tree; void dfs1(int v, int pop) { dp_node[v].sub_siz = 1; dp_node[v].is_win = 0; rep(d1,2) rep(d2,2) dp_node[v].dp[d1][d2] = 0; int los_cnt = 0; forall(it,graph[v]) { if(it != pop) { dfs1(it,v); if(!dp_node[it].is_win) los_cnt++; dp_node[v].sub_siz += dp_node[it].sub_siz; } } if(los_cnt > 0) dp_node[v].is_win = 1; if(los_cnt >= 2) { dp_node[v].dp[1][0] = dp_node[v].sub_siz; dp_node[v].dp[1][1] = dp_node[v].sub_siz; dp_node[v].dp[0][0] = 0; dp_node[v].dp[0][1] = 0; } else if(los_cnt == 1) { int los_vert; forall(it,graph[v]) { if(it != pop && !dp_node[it].is_win) los_vert = it; } dp_node[v].dp[1][1] = dp_node[v].sub_siz - dp_node[los_vert].sub_siz + dp_node[los_vert].dp[0][1]; dp_node[v].dp[1][0] = dp_node[v].sub_siz - dp_node[los_vert].sub_siz + dp_node[los_vert].dp[0][0]; dp_node[v].dp[0][1] = dp_node[los_vert].dp[1][1]; dp_node[v].dp[0][0] = dp_node[los_vert].dp[1][0]; } else { dp_node[v].dp[1][0] = 1; dp_node[v].dp[0][1] = 1; forall(it,graph[v]) { if(it != pop) { dp_node[v].dp[1][1] += dp_node[it].dp[0][1]; dp_node[v].dp[1][0] += dp_node[it].dp[0][0]; dp_node[v].dp[0][1] += dp_node[it].dp[1][1]; dp_node[v].dp[0][0] += dp_node[it].dp[1][0]; } } } } void dfs2(int v, int pop) { node old_dp = dp_node[v]; dp_node[v].sub_siz = 1; dp_node[v].is_win = 0; rep(d1,2) rep(d2,2) dp_node[v].dp[d1][d2] = 0; int los_cnt = 0; forall(it,graph[v]) { if(!dp_node[it].is_win) los_cnt++; dp_node[v].sub_siz += dp_node[it].sub_siz; } if(los_cnt > 0) dp_node[v].is_win = 1; vi los_verts; forall(it,graph[v]) { if(!dp_node[it].is_win) { los_verts.pb(it); } } if(los_cnt >= 2) { dp_node[v].dp[1][0] = dp_node[v].sub_siz; dp_node[v].dp[1][1] = dp_node[v].sub_siz; dp_node[v].dp[0][0] = 0; dp_node[v].dp[0][1] = 0; } else if(los_cnt == 1) { int los_vert; forall(it,graph[v]) { if(!dp_node[it].is_win) { los_vert = it; } } dp_node[v].dp[1][1] = dp_node[v].sub_siz - dp_node[los_vert].sub_siz + dp_node[los_vert].dp[0][1]; dp_node[v].dp[1][0] = dp_node[v].sub_siz - dp_node[los_vert].sub_siz + dp_node[los_vert].dp[0][0]; dp_node[v].dp[0][1] = dp_node[los_vert].dp[1][1]; dp_node[v].dp[0][0] = dp_node[los_vert].dp[1][0]; } else { dp_node[v].dp[1][0] = 1; dp_node[v].dp[0][1] = 1; forall(it,graph[v]) { dp_node[v].dp[1][1] += dp_node[it].dp[0][1]; dp_node[v].dp[1][0] += dp_node[it].dp[0][0]; dp_node[v].dp[0][1] += dp_node[it].dp[1][1]; dp_node[v].dp[0][0] += dp_node[it].dp[1][0]; } } if(dp_node[v].is_win) end_tree.dp[1][1]++; else end_tree.dp[0][1]++; rep(d1,2) rep(d2,2) { mid_tree.dp[d1][d2] += dp_node[v].dp[d1][d2]; mid_tree.dp[d1][d2] %= MOD; } forall(it,graph[v]) { if(it != pop) { node prev_node = dp_node[v]; if(!dp_node[it].is_win) los_cnt--; dp_node[v].sub_siz -= dp_node[it].sub_siz; if(los_cnt == 0) dp_node[v].is_win = 0; else dp_node[v].is_win = 1; if(los_cnt >= 2) { dp_node[v].dp[1][0] = dp_node[v].sub_siz; dp_node[v].dp[1][1] = dp_node[v].sub_siz; dp_node[v].dp[0][0] = 0; dp_node[v].dp[0][1] = 0; } else if(los_cnt == 1) { int los_vert = los_verts[0]; if(los_vert == it) los_vert = los_verts[1]; dp_node[v].dp[1][1] = dp_node[v].sub_siz - dp_node[los_vert].sub_siz + dp_node[los_vert].dp[0][1]; dp_node[v].dp[1][0] = dp_node[v].sub_siz - dp_node[los_vert].sub_siz + dp_node[los_vert].dp[0][0]; dp_node[v].dp[0][1] = dp_node[los_vert].dp[1][1]; dp_node[v].dp[0][0] = dp_node[los_vert].dp[1][0]; } else { if(dp_node[it].is_win) { dp_node[v].dp[1][1] -= dp_node[it].dp[0][1]; dp_node[v].dp[1][0] -= dp_node[it].dp[0][0]; dp_node[v].dp[0][1] -= dp_node[it].dp[1][1]; dp_node[v].dp[0][0] -= dp_node[it].dp[1][0]; } else { dp_node[v].dp[1][0] = 1; dp_node[v].dp[0][1] = 1; dp_node[v].dp[1][1] = 0; dp_node[v].dp[0][0] = 0; forall(it2,graph[v]) { if(it == it2) continue; dp_node[v].dp[1][1] += dp_node[it2].dp[0][1]; dp_node[v].dp[1][0] += dp_node[it2].dp[0][0]; dp_node[v].dp[0][1] += dp_node[it2].dp[1][1]; dp_node[v].dp[0][0] += dp_node[it2].dp[1][0]; } } } dfs2(it,v); dp_node[v] = prev_node; if(!dp_node[it].is_win) los_cnt++; } } dp_node[v] = old_dp; } int main() { ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); //random_start(); int n; ll D; cin >> n >> D; rep(i,n-1) { int a,b; cin >> a >> b; graph[a].pb(b); graph[b].pb(a); } dfs1(1,1); rep(d1,2) rep(d2,2) { beg_tree.dp[d1][d2] = dp_node[1].dp[d1][d2]; } dfs2(1,1); D--; rep2(bit,0,61) { if(D & (1LL << bit)) { beg_tree = beg_tree + mid_tree; } mid_tree = mid_tree + mid_tree; } beg_tree = beg_tree + end_tree; cout << beg_tree.dp[1][1] << "\n"; }
#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...