public static MatrixLong operator *(MatrixLong a, MatrixLong b) { if (a == null) { throw new ArgumentNullException("a"); } if (b == null) { throw new ArgumentNullException("b"); } if (a.Cols != b.Rows) { throw new ArgumentException("Invalid matrix dimensions"); } MatrixLong c = new MatrixLong(a.Rows, b.Cols); for (int i = 0; i < a.Rows; i++) { for (int j = 0; j < b.Cols; ++j) { for (int k = 0; k < a.Cols; ++k) { c._Data[i, j] += NumTheoryUtils.Mul(a._Data[i, k], b._Data[k, j], MOD); if (c._Data[i, j] >= MOD) { c._Data[i, j] -= MOD; } } } } return(c); }
public void ArithmeticsMustWork() { for (int i = -100; i <= 100; ++i) { for (int j = -100; j <= 100; ++j) { for (int mod = 1; mod <= 1000; ++mod) { Assert.AreEqual(((i * j) % mod + mod) % mod, NumTheoryUtils.Mul(i, j, mod)); } } } long mx = 1000000000000000000L; for (int i = -10; i <= 10; ++i) { for (int j = -10; j <= 10; ++j) { for (int mod = 1; mod <= 100; ++mod) { var bi = new BigInteger(mx - i); var bj = new BigInteger(mx - j); var bmod = new BigInteger(mx - mod); Assert.AreEqual((((bi * bj) % bmod + bmod) % bmod).ToString(), NumTheoryUtils.Mul(mx - i, mx - j, mx - mod).ToString(), string.Format("{0}*{1} modulo {2}", bi, bj, bmod)); bi = new BigInteger(-mx + i); bj = new BigInteger(mx - j); bmod = new BigInteger(mx - mod); Assert.AreEqual((((bi * bj) % bmod + bmod) % bmod).ToString(), NumTheoryUtils.Mul(i - mx, mx - j, mx - mod).ToString(), string.Format("{0}*{1} modulo {2}", bi, bj, bmod)); bi = new BigInteger(mx - i); bj = new BigInteger(mx - j); bmod = new BigInteger(mod); Assert.AreEqual((((bi * bj) % bmod + bmod) % bmod).ToString(), NumTheoryUtils.Mul(mx - i, mx - j, mod).ToString(), string.Format("{0}*{1} modulo {2}", bi, bj, bmod)); bi = new BigInteger(-mx + i); bj = new BigInteger(mx - j); bmod = new BigInteger(mod); Assert.AreEqual((((bi * bj) % bmod + bmod) % bmod).ToString(), NumTheoryUtils.Mul(i - mx, mx - j, mod).ToString(), string.Format("{0}*{1} modulo {2}", bi, bj, bmod)); } } } }
void Solve() { ans = 0; edges = new int[26, 26]; for (int i = 0; i < n; ++i) { var letters = new List <char>(); for (int j = 0; j < s[i].Length;) { int k = j + 1; while (k < s[i].Length && s[i][k] == s[i][j]) { ++k; } letters.Add(s[i][j]); j = k; } if (letters.Distinct().Count() != letters.Count) { return; } if (letters.Count < 3) { edges[letters[0] - 'a', letters[letters.Count - 1] - 'a']++; } else { for (int j = 1; j < letters.Count - 1; ++j) { for (int l = 0; l < n; ++l) { if (l != i && s[l].IndexOf(letters[j]) >= 0) { return; } } } edges[letters[0] - 'a', letters[letters.Count - 1] - 'a']++; } } int[] to = new int[26]; int[] from = new int[26]; for (int i = 0; i < 26; ++i) { to[i] = -1; from[i] = -1; } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (i != j && edges[i, j] > 0) { if (to[i] != -1) { return; } to[i] = j; from[j] = i; } } if (to[i] != -1 && edges[i, to[i]] > 1) { return; } } int[] f = NumTheoryUtils.FactorialArray(1000, MOD); bool[] was = new bool[26]; int counted = 0; int curAns = 1; int chains = 0; for (int i = 0; i < 26; ++i) { if (from[i] == -1) { if (to[i] != -1 || edges[i, i] > 0) { ++chains; } int u = i; while (u != -1 && !was[u]) { was[u] = true; curAns = NumTheoryUtils.Mul(curAns, f[edges[u, u]], MOD); counted += edges[u, u] + (to[u] == -1 ? 0 : 1); u = to[u]; } if (u != -1) { ans = 0; return; } } } if (counted != n) { ans = 0; return; } curAns = NumTheoryUtils.Mul(curAns, f[chains], MOD); ans = curAns; }