제출 #1363511

#제출 시각아이디문제언어결과실행 시간메모리
1363511TraianDanciuStar Trek (CEOI20_startrek)C++20
38 / 100
48 ms20604 KiB
#include <iostream>
#include <vector>

using namespace std;

const int MAXN = 100000;
const int MOD = 1000000007;

vector<int> g[MAXN + 1];
int n, sz[MAXN + 1], down[MAXN + 1], down_move[MAXN + 1];
int cnt, can_win[MAXN + 1], win_move[MAXN + 1], p[MAXN + 1];

void subSelf(int &a, int b) {
  a -= b;
  if(a < 0) {
    a += MOD;
  }
}

void addSelf(int &a, int b) {
  a += b;
  if(a >= MOD) {
    a -= MOD;
  }
}

struct Rec {
  int a, b; // a * N^(2*d-1) + b * win_cnt

  void operator -=(const Rec &other) {
    subSelf(a, other.a);
    subSelf(b, other.b);
  }

  void operator +=(const Rec &other) {
    addSelf(a, other.a);
    addSelf(b, other.b);
  }
} rec_down[MAXN + 1], rec_up[MAXN + 1], rec_win[MAXN + 1], sum_sons[MAXN + 1], next_cnt;

struct Matrix {
  int val[2][2];
};

Matrix operator *(Matrix a, Matrix b) {
  Matrix c;
  for(int i = 0; i < 2; i++) {
    for(int j = 0; j < 2; j++) {
      c.val[i][j] = 0;
      for(int k = 0; k < 2; k++) {
        c.val[i][j] = (c.val[i][j] + 1LL * a.val[i][k] * b.val[k][j]) % MOD;
      }
    }
  }
  return c;
}

void dfs(int node, int parent) {
  p[node] = parent;
  sz[node] = 1;
  for(int son : g[node]) {
    if(son != parent) {
      dfs(son, node);
      sum_sons[node] += rec_down[son];
      sz[node] += sz[son];
      if(down[son] == 0) {
        down[node]++;
        down_move[node] = son;
      }
    }
  }

  rec_down[node].a = sz[node];
  if(down[node] == 0) {
    rec_down[node].b = MOD - 1;
    rec_down[node] -= sum_sons[node];
  } else if(down[node] == 1) {
    rec_down[node] -= rec_down[down_move[node]];
  }
}

void dfs2(int node, int parent) {
  can_win[node] = down[node];
  win_move[node] = down_move[node];
  if(node > 1 && (can_win[parent] == 0 || (can_win[parent] == 1 && win_move[parent] == node))) {
    can_win[node]++;
    win_move[node] = parent;
  }
  if(can_win[node] > 0) {
    cnt++;
  }
  for(int son : g[node]) {
    if(son != parent) {
      dfs2(son, node);
    }
  }
}

void dfs3(int node, int parent) {
  if(node > 1) {
    rec_up[node].a = n - sz[node];
    if(can_win[parent] == 0) {
      rec_up[node].b = MOD - 1;
      rec_up[node] -= rec_up[parent];
      rec_up[node] -= sum_sons[parent];
      rec_up[node] += rec_down[node];
    } else if(can_win[parent] == 1) {
      if(win_move[parent] == p[parent]) {
        rec_up[node] -= rec_up[parent];
      } else {
        rec_up[node] -= rec_down[win_move[parent]];
      }
    }
  }
  rec_win[node].a = n;
  if(can_win[node] == 0) {
    rec_win[node].b = MOD - 1;
    rec_win[node] -= rec_up[parent];
    rec_win[node] -= sum_sons[node];
  } else if(can_win[node] == 1) {
    if(win_move[node] == parent) {
      rec_win[node] -= rec_up[parent];
    } else {
      rec_win[node] -= rec_down[win_move[node]];
    }
  }
  next_cnt += rec_win[node];
  for(int son : g[node]) {
    if(son != parent) {
      dfs3(son, node);
    }
  }
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  long long d;
  cin >> n >> d;
  for(int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }

  dfs(1, 0);
  dfs2(1, 0);
  dfs3(1, 0);

  Matrix aux;
  aux.val[0][0] = n;
  aux.val[0][1] = 0;
  aux.val[1][0] = 0;
  aux.val[1][1] = cnt;

  Matrix rec;
  rec.val[0][0] = 1LL * n * n % MOD;
  rec.val[0][1] = next_cnt.a;
  rec.val[1][0] = 0;
  rec.val[1][1] = next_cnt.b;

  d--;
  while(d > 0) {
    if(d & 1) {
      aux = aux * rec;
    }
    rec = rec * rec;
    d >>= 1;
  }

  cout << (1LL * aux.val[0][0] * rec_win[1].a + 1LL * aux.val[1][1] * rec_win[1].b) % MOD << "\n";
  return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…