int m, n; vector a(m); // a[i,0]..a[i,n-1],b[i] // a[i].size() == n+1 // x1,x2,...,xn // int b[m]; // n^3 : любое поле // поля : R, C, F_2, F_p, F_{2^32} void Gauss() { for (int i = 0; i < m; i++) { int j = i; while (a[j][i] == 0) j++; swap(a[i], a[j]); // det *= -1 // swap(b[i], b[j]); // a[i][i] != 0 for (int j = 0; j < n; j++) if (j != i) // диагональная // if (j > i) // треугольная { // double coef = a[j][i] / a[i][i] // a[j] -= a[i] * coef; // O(n) --> n^3 // for (int k = i; k < n; k++) // a[j][k] -= a[i][k] * coef; a[j] ^= a[i]; // bitset, n/w linears[j] ^= linears[i]; // bitset, n/w } } } // диагональная : sum_i (n^2 * i) = n^3 / 2 // треугольная : sum_i (n-i)^2 = n^3 / 3 detA = a[0][0] * a[1][1] * ... * a[n-1][n-1] Восстановление x | Ax=b x[i] = b[i] / a[i][i] | O(n) x[i] = (b[i] - sum_{j>i} a[j][i]*x[j]) / a[i][i] | O(n^2) // Гаусс для построения базиса vector> basis; vector ind; // a[ind[i]] -> 0 const double EPS = 1e-6; bool isZero(double x) { return abs(x) < EPS; } void Add(vector a) { for (size_t i = 0; i < basis.size(); i++) if (!isZero(a[ind[i]])) { double coef = a[ind[i]] / basis[i][ind[i]] for (size_t k = 0; k < a.size(); k++) a[k] -= basis[i][k] * coef; } size_t j = 0; while (j < a.size() && isZero(a[j])) j++; if (j == a.size()) return; // линейная комбинация basis.push_back(a); ind.push_back(j); } // m векторов // длины n // размер базиса k // m * kn = O(mnk) k<=min(n,m) // n*m*min(n,m) void Add(int i, vector a) { vector linear(N); linear[i] = 1; for (size_t i = 0; i < basis.size(); i++) if (!isZero(a[ind[i]])) { double coef = a[ind[i]] / basis[i][ind[i]] for (size_t k = 0; k < a.size(); k++) { a[k] -= basis[i][k] * coef; } for (size_t k = 0; k < linear.size(); k++) { linear[k] -= basisLinear[i][k] * coef; } } size_t j = 0; while (j < a.size() && isZero(a[j])) j++; if (j == a.size()) return; // линейная комбинация basis.push_back(a); basisLinear.push_back(linear); ind.push_back(j); }