Пример #1
0
        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);
        }
Пример #2
0
        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));
                    }
                }
            }
        }
Пример #3
0
        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;
        }