Submission #585821

#TimeUsernameProblemLanguageResultExecution timeMemory
58582179brueStar Trek (CEOI20_startrek)C++17
50 / 100
32 ms8320 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD = 1000000007; struct Matrix{ int n, m; ll mat[2][2]; Matrix(){} Matrix(int n, int m): n(n), m(m){ for(int i=0; i<n; i++) for(int j=0; j<m; j++) mat[i][j] = 0; } Matrix operator*(const Matrix &r)const{ assert(m == r.n); Matrix ret (n, r.m); for(int i=0; i<n; i++){ for(int j=0; j<m; j++){ for(int k=0; k<r.m; k++){ ret.mat[i][k] += mat[i][j] * r.mat[j][k]; ret.mat[i][k] %= MOD; } } } return ret; } }; ll mpow(ll x, ll y){ if(!y) return 1; if(y%2) return mpow(x, y-1) * x % MOD; ll tmp = mpow(x, y/2); return tmp*tmp%MOD; } Matrix BasicMatrix(int n, int m){ Matrix mat (n, m); assert(n==m); for(int i=0; i<n; i++) mat.mat[i][i] = 1; return mat; } Matrix mpow(Matrix x, ll y){ if(!y) return BasicMatrix(x.n, x.m); if(y&1) return mpow(x, y-1) * x; Matrix tmp = mpow(x, y/2); return tmp * tmp; } ll n; ll k; vector<int> link[1002]; ll mat[1002][1002]; ll depth[1002]; ll group[1002], groupCnt[2]; ll ans; ll DP[2][1002]; ll find1[1002], find2[1002]; void dfs(int x, int p, int r){ if(r==1){ group[x] = depth[x]%2; groupCnt[group[x]]++; } for(auto y: link[x]){ if(y==p) continue; depth[y] = depth[x] + 1; dfs(y, x, r); if(!mat[r][y]) mat[r][x] = 1; } } int dfsFind(int x, int p, int dp, int r){ /// 무조건 지나야 하는 상대 차례 점 개수 찾기 if(dp % 2 == 0){ /// my turn int cnt = 0; for(auto y: link[x]){ if(y!=p && !mat[r][y]) cnt++; } if(cnt > 1) return 0; assert(cnt == 1); for(auto y: link[x]){ if(y!=p && !mat[r][y]) return dfsFind(y, x, dp+1, r); } exit(1); } else{ /// your turn int ret = 1; for(auto y: link[x]){ if(y==p) continue; ret += dfsFind(y, x, dp+1, r); } return ret; } } int dfsFind2(int x, int p, int dp, int r){ if(dp % 2 == 0){ /// my turn int ret = 1; for(auto y: link[x]){ if(y==p) continue; ret += dfsFind2(y, x, dp+1, r); } return ret; } else{ /// your turn int cnt = 0; for(auto y: link[x]){ if(y!=p && !mat[r][y]) cnt++; } if(cnt > 1) return 0; assert(cnt == 1); for(auto y: link[x]){ if(y!=p && !mat[r][y]) return dfsFind2(y, x, dp+1, r); } exit(1); } } int main(){ scanf("%lld %lld", &n, &k); for(int i=1; i<n; i++){ int x, y; scanf("%d %d", &x, &y); link[x].push_back(y); link[y].push_back(x); } // for(int i=n; i>=1; i--){ // for(int x=0; x<=n+1; x++) depth[x] = DP[x] = 0; // dfs(i), DProot[i] = DP[i]; // } // for(int i=1; i<=n; i++) printf("%d ", DProot[i]); for(int i=1; i<=n; i++){ dfs(i, -1, i); if(mat[i][i]) find1[i] = groupCnt[!group[i]] - dfsFind(i, -1, 0, i); else find2[i] = dfsFind2(i, -1, 0, i); DP[0][i] = mat[i][i]; } Matrix first (1, 2); first.mat[0][0] = first.mat[0][1] = 0; for(int i=1; i<=n; i++){ if(mat[i][i]) first.mat[0][0]++; else first.mat[0][1]++; } Matrix multiplier (2, 2); /// 0: WIN, 1: LOSE for(int i=1; i<=n; i++){ if(mat[i][i]){ multiplier.mat[0][0] = (multiplier.mat[0][0] + n) % MOD; multiplier.mat[1][0] = (multiplier.mat[1][0] + groupCnt[group[i]]) % MOD; multiplier.mat[1][0] = (multiplier.mat[1][0] + find1[i]) % MOD; multiplier.mat[1][1] = (multiplier.mat[1][1] + n - groupCnt[group[i]] - find1[i] + MOD)%MOD; } else{ multiplier.mat[1][0] = (multiplier.mat[1][0] + find2[i]) % MOD; multiplier.mat[0][1] = (multiplier.mat[0][1] + n) % MOD; multiplier.mat[1][1] = (multiplier.mat[1][1] + n - find2[i]) % MOD; } } multiplier = mpow(multiplier, k-1); first = first * multiplier; ll Wsum = first.mat[0][0], Lsum = first.mat[0][1]; ll ans = 0; if(mat[1][1]){ ans = (Wsum * n + groupCnt[group[1]] * Lsum + find1[1] * Lsum) % MOD; } else ans = find2[1] * Lsum % MOD; // int b = turn%2; // // /// 전처리 // ll Wsum = 0; /// 이기는 가짓수 // for(int i=1; i<=n; i++) Wsum = (Wsum + DP[!b][i]) % MOD; // ll Lsum = (mpow(n, 2*turn-1) - Wsum + MOD) % MOD; /// 지는 가짓수 // // /// 실제 계산 // for(int i=1; i<=n; i++){ // DP[b][i] = 0; // if(mat[i][i]){ /// 여기서 시작하면 이기는 경우 // /// ? -> W // DP[b][i] = (DP[b][i] + Wsum * n) % MOD; // /// my turn -> L // DP[b][i] = (DP[b][i] + groupCnt[group[i]] * Lsum) % MOD; // /// your turn -> L // DP[b][i] = (DP[b][i] + find1[i] * Lsum) % MOD; // } // else{ // DP[b][i] = (DP[b][i] + find2[i] * Lsum) % MOD; // } // } // } printf("%lld", ans); }

Compilation message (stderr)

startrek.cpp: In function 'int main()':
startrek.cpp:123:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  123 |     scanf("%lld %lld", &n, &k);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~
startrek.cpp:126:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  126 |         scanf("%d %d", &x, &y);
      |         ~~~~~^~~~~~~~~~~~~~~~~
#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...