-
Notifications
You must be signed in to change notification settings - Fork 61
Expand file tree
/
Copy path1916-count-ways-to-build-rooms-in-an-ant-colony.js
More file actions
71 lines (61 loc) · 2.15 KB
/
1916-count-ways-to-build-rooms-in-an-ant-colony.js
File metadata and controls
71 lines (61 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 1916. Count Ways to Build Rooms in an Ant Colony
* https://leetcode.com/problems/count-ways-to-build-rooms-in-an-ant-colony/
* Difficulty: Hard
*
* You are an ant tasked with adding n new rooms numbered 0 to n-1 to your colony. You are given
* the expansion plan as a 0-indexed integer array of length n, prevRoom, where prevRoom[i]
* indicates that you must build room prevRoom[i] before building room i, and these two rooms
* must be connected directly. Room 0 is already built, so prevRoom[0] = -1. The expansion plan
* is given such that once all the rooms are built, every room will be reachable from room 0.
*
* You can only build one room at a time, and you can travel freely between rooms you have
* already built only if they are connected. You can choose to build any room as long as its
* previous room is already built.
*
* Return the number of different orders you can build all the rooms in. Since the answer may
* be large, return it modulo 109 + 7.
*/
/**
* @param {number[]} prevRoom
* @return {number}
*/
var waysToBuildRooms = function(prevRoom) {
const n = prevRoom.length;
const mod = 1e9 + 7;
const graph = Array(n).fill().map(() => []);
const factorial = Array(n + 1).fill(1n);
const invFactorial = Array(n + 1).fill(1n);
for (let i = 1; i <= n; i++) {
factorial[i] = (factorial[i - 1] * BigInt(i)) % BigInt(mod);
}
for (let i = 1; i <= n; i++) {
invFactorial[i] = modInverse(factorial[i], BigInt(mod));
}
for (let i = 1; i < n; i++) {
graph[prevRoom[i]].push(i);
}
return Number(countSubtreeSizes(0)[1]);
function countSubtreeSizes(node) {
let size = 1;
let result = 1n;
for (const child of graph[node]) {
const [childSize, childResult] = countSubtreeSizes(child);
size += childSize;
result = (result * childResult * invFactorial[childSize]) % BigInt(mod);
}
return [size, (result * factorial[size - 1]) % BigInt(mod)];
}
function modInverse(a, m) {
const m0 = m;
let q;
let x0 = 0n;
let x1 = 1n;
while (a > 1n) {
q = a / m;
[a, m] = [m, a % m];
[x0, x1] = [x1 - q * x0, x0];
}
return x1 < 0n ? x1 + m0 : x1;
}
};