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
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#include <cstdio>
#include <cstdint>
#include <cassert>
#include <utility>

static const uint64_t MODULUS = 1000 * 1000 * 1000 + 7;
static uint8_t numbers[2 * 1000 * 1000 + 1];
static uint32_t factorials[4 * 1000 * 1000 + 1];
static uint32_t inverse_factorials[4 * 1000 * 1000 + 1];
static uint32_t inverses[4 * 1000 * 1000 + 1];
static uint32_t pows_of_two[4 * 1000 * 1000 + 1];
static uint32_t inverse_pows_of_two[4 * 1000 * 1000 + 1];

constexpr static uint32_t add_wrapping(uint32_t a, uint32_t b) {
    return (uint64_t(a) + uint64_t(b)) % MODULUS;
}

// constexpr static uint32_t neg_wrapping(uint32_t a) {
//     return (MODULUS - uint64_t(a)) % MODULUS;
// }

constexpr static uint32_t mul_wrapping(uint32_t a, uint32_t b) {
    return (uint64_t(a) * uint64_t(b)) % MODULUS;
}

constexpr static std::pair<int32_t, int32_t> extended_euclid(int32_t a, int32_t b) {
    if (b == 0) {
        return {1, 0};
    } else {
        const auto [x, y] = extended_euclid(b, a - (a / b) * b);
        return {y, x - (a / b) * y};
    }
}

constexpr static uint32_t inverse_wrapping(uint32_t a) {
    auto [x, y] = extended_euclid(MODULUS, a);
    if (y < 0) {
        y += MODULUS;
    }
    return y;
}

uint32_t solve() {
    int n;
    scanf("%d", &n);

    int seen = 0;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        assert(x >= 0 && x <= 2);
        assert(y >= 0 && y <= 2);
        seen |= 1 << x;
        seen |= 1 << y;
        numbers[2*i+0] = x;
        numbers[2*i+1] = y;
    }

    if ((seen & (1 << 0)) && (seen & (1 << 2))) {
        // No valid solution if both 0 and 2 appears in the input
        return 0;
    }

    if (seen & (1 << 2)) {
        int prev = numbers[2*n-1];
        for (int i = 0; i <= n; i++) {
            int curr = numbers[i];
            numbers[i] = 2 - prev;
            prev = curr;
        }
        if (seen & (1 << 2)) {
            seen -= (1 << 2);
            seen += (1 << 0);
        }
    }
    // Now, all values are either 0 or 1

    // Precompute stuff
    // TODO: Only calculate what's needed, reuse results from the previous test case
    factorials[0] = 1;
    inverses[0] = 0;
    inverse_factorials[0] = 1;
    pows_of_two[0] = 1;
    inverse_pows_of_two[0] = 1;
    const uint32_t inverse_2 = inverse_wrapping(2);
    for (int i = 1; i <= 4*n; i++) {
        factorials[i] = mul_wrapping(i, factorials[i-1]);
        inverses[i] = inverse_wrapping(i);
        inverse_factorials[i] = mul_wrapping(inverses[i], inverse_factorials[i-1]);
        pows_of_two[i] = mul_wrapping(pows_of_two[i-1], 2);
        inverse_pows_of_two[i] = mul_wrapping(inverse_pows_of_two[i-1], inverse_2);

        // fprintf(stderr,
        //         "[%d] factorials: %d, inverses: %d, inverse_factorials: %d, pows_of_two: %d, inverse_pows_of_two: %d\n",
        //         i, factorials[i], inverses[i], inverse_factorials[i], pows_of_two[i], inverse_pows_of_two[i]);
    }

    if (seen == (1 << 0)) {
        // Special case: all zeros
        // We need to count all possible card configurations where the team A
        // has two best cards.

        // For the best two cards, select two unique players (n * (n - 1))
        const uint32_t best_two_different_player_choices = mul_wrapping(n, n - 1);
        // Choose the configuration for remaining cards
        const uint32_t remaining_choices_for_two_different_players = (n > 1)
                ? mul_wrapping(factorials[4*n-2], inverse_pows_of_two[2*n-2])
                : 0;

        // Alternatively, select one player and give them two cards
        const uint32_t best_one_same_player_choices = n;
        // Choose the configuration for remaining cards
        const uint32_t remaining_choices_for_one_same_player = mul_wrapping(factorials[4*n-2], inverse_pows_of_two[2*n-1]);

        // fprintf(stderr, "best two different player choices: %d\n", best_two_different_player_choices);
        // fprintf(stderr, "remaining choices for two different players: %d\n", remaining_choices_for_two_different_players);
        // fprintf(stderr, "best one same player choices: %d\n", best_one_same_player_choices);
        // fprintf(stderr, "remaining choices for one same player: %d\n", remaining_choices_for_one_same_player);

        return add_wrapping(
            mul_wrapping(best_two_different_player_choices, remaining_choices_for_two_different_players),
            mul_wrapping(best_one_same_player_choices, remaining_choices_for_one_same_player)
        );
    } else if (seen == (1 << 1)) {
        // Special case: all ones

        // Two variants: either A has the best card and B has two following cards,
        // or vice versa. The cases are completely symmetric so we'll just multiply
        // by two.
        const uint32_t second_best_two_player_choices = mul_wrapping(n, n - 1);
        const uint32_t second_best_one_player_choices = n;

        // fprintf(stderr, "second best two player choices: %d\n", second_best_two_player_choices);
        // fprintf(stderr, "second best one player choices: %d\n", second_best_one_player_choices);

        const uint32_t configs_without_best = add_wrapping(
            (n > 1) ? mul_wrapping(second_best_two_player_choices, mul_wrapping(factorials[4*n-3], inverse_pows_of_two[2*n-3])) : 0,
            mul_wrapping(second_best_one_player_choices, mul_wrapping(factorials[4*n-3], inverse_pows_of_two[2*n-2]))
        );

        // fprintf(stderr, "configs without best: %d\n", configs_without_best);

        // Account for the best card here
        return mul_wrapping(2 * n, configs_without_best);
    } else {
        // General case

        // Count the groups of ones, also do verification
        int num_groups = 0;
        int canonical_gap_start = 0;
        for (int i = 0; i < n; i++) {
            const int x = numbers[2*i+0];
            const int y = numbers[2*i+1];
            if (x == 0 && y == 1) {
                // Impossible case
                return 0;
            } else if (x == 1 && y == 1) {
                const int ii = (i + 1) % n;
                if (numbers[2*ii+0] == 0) { // No need to check y == 0, it's implied by x
                    // Improperly terminated group
                    return 0;
                }
            } else if (x == 1 && y == 0) {
                // Group terminator
                num_groups++;
                canonical_gap_start = i+1;
            }
        }

        uint32_t paa_count = 0;

        // Align with a start of a gap, then look at how big the gaps are
        int last_group_start = 0;
        for (int j = 0; j < n; j++) {
            const int i = (canonical_gap_start + j) % n;
            const int x = numbers[2*i+0];
            if (x == 0) { // No need to check y == 0, it's implied by x
                if (j > last_group_start) {
                    // Choose one P, choose two A
                    paa_count = add_wrapping(paa_count, mul_wrapping(j - last_group_start, mul_wrapping(j - last_group_start, j - last_group_start)));
                }
                last_group_start = j + 1;
            }
        }

        // fprintf(stderr, "Groups: %d\n", num_groups);
        // fprintf(stderr, "PAA count: %u\n", paa_count);

        uint32_t result = 0;

        // Variant 1: normal stairs, 2P just below
        // Choose the highest 2 P players, then choose the rest arbitrarily
        uint32_t choices_of_2p = 0;
        if (num_groups <= n - 2) {
            choices_of_2p = add_wrapping(choices_of_2p, mul_wrapping(
                // Choose two of not chosen for any group
                mul_wrapping(n - num_groups, n - num_groups),
                mul_wrapping(
                    factorials[4*n - 2 * num_groups - 2],
                    inverse_pows_of_two[2*n - 2 * num_groups - 2]
                )
            ));
            // fprintf(stderr, "Choices of 2P after including out-group units: %u\n", choices_of_2p);
        }
        if (num_groups <= n - 1) {
            choices_of_2p = add_wrapping(choices_of_2p, mul_wrapping(
                // Choose one from the groups and the other from others
                mul_wrapping(num_groups, n - num_groups),
                mul_wrapping(
                    factorials[4*n - 2 * num_groups - 1],
                    inverse_pows_of_two[2*n - 2 * num_groups - 1]
                )
            ));
            // fprintf(stderr, "Choices of 2P after including out-and-not-out-group units: %u\n", choices_of_2p);
        }
        choices_of_2p = add_wrapping(choices_of_2p, mul_wrapping(
            // Choose both from the groups
            mul_wrapping(num_groups, num_groups),
            mul_wrapping(
                factorials[4*n - 2 * num_groups],
                inverse_pows_of_two[2*n - 2 * num_groups]
            )
        ));
        // fprintf(stderr, "Choices of 2P after including ingroup units: %u\n", choices_of_2p);

        result = add_wrapping(result, mul_wrapping(num_groups, choices_of_2p));
        // fprintf(stderr, "Result now is: %u\n", result);

        // Variant 2: one stair is substituted by this horrible PAA thing
        // Not implemented!
        // fprintf(stderr, "Result now is: %u\n", result);

        return result;
    }

    return 0;
}

int main() {
    int t;
    scanf("%d", &t);

    while (t --> 0) {
        printf("%llu\n", (unsigned long long int)solve());
    }

    return 0;
}