#include #include #include #include #include "validation.h" using namespace std; // Invert a given matrix, specified in row-major order. Throws exception when // input is not a square matrix or is not invertible. // // The algorithm below is based on the following idea: Let U be the input // matrix, and assume it is invertible. Then U U^{-1} = 1. If we were to find // some series of matrices A_1, ... , A_n such that A_n A_{n-1} ... A_1 U = 1, // then U^{-1} = A_n A_{n-1} ... A_1 // // The code below uses three basic operations: // - Swapping two rows // - Multiplying a row by a non-zero rational // - Adding a multiple of one row to another // all of which can be represented as invertable matrices, to find a sequence // of operations that reduce U to the identity. It simultaneously applies the // same sequence to an identiy matrix to construct U^{-1}. // // It does this in two steps: // - First, it reduces U to an upper triangular form, with only 1s on the // diagonal. (It is trivial to see this is always possible for invertible // matrices, as the identiy matrix satisfies this requirement) // - Second, it goes back through the matrix to eliminate all off-diagonal // non-zero elements. // After these steps, the output matrix will contain the inverse of the input // matrix. // // Complexity: O(N^3), where N is the number of rows (equivalently: colums) in // the matrix. vector> MatrixInverse(vector> in) { // Check that the input is indeed a square matrix size_t N = in.size(); if (N < 1) throw "No input"; for (size_t i=0; i> out(N, vector(N, 0_mpq)); for (size_t i=0; i= i) with a non-zero value // in column i size_t j; for (j=i; j0; i--) { // row 0 wont sweep out anything so this is ok for (size_t j=0; j CalculateRatio(vector> configuration, int c, int d) { size_t N = configuration.size() + 2; if (N == 2) { // No splitters, so no output return make_pair(0_mpq, 0_mpq); } // Rewrite c and d into fractions mpq_class Crat(c, c+d), Drat(d, c+d); Crat.canonicalize(); // Required since we don't know whether c and d Drat.canonicalize(); // share a factor // Write equations in matrix form, shifting indices up 2 so -1 and -2 // become >= 0. vector> equations(N, vector(N, 0_mpq)); for (size_t i=0; i> in) { for (auto v : in) { for (auto u : v) { cout << u << " "; } cout << endl; } } // Main is responsible for parsing the user output and doing the actual check that ratios are reasonable. int main(int argc, char **argv) { // Set up the input and answer streams. std::ifstream in(argv[1]); // testcase input OutputValidator v(argc, argv); // team output // read problem statement parameters a, b, c and d int a,b,c,d; in >> a >> b >> c >> d; // read user solution int n = v.read_int(1,200); v.newline(); vector> configuration(n); for (int i=0; i reach(n, false); queue work; reach[0] = true; work.push(0); while (!work.empty()) { int cur = work.front(); work.pop(); if (configuration[cur].first >= 0) { if (!reach[configuration[cur].first]) { reach[configuration[cur].first] = true; work.push(configuration[cur].first); } } if (configuration[cur].second >= 0) { if (!reach[configuration[cur].second]) { reach[configuration[cur].second] = true; work.push(configuration[cur].second); } } } for (int i=0; i