码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3659Which Dreamed It

时间:2019-10-02 23:22:17      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:lag   void   bool   ret   flag   break   code   直接   names   

Solution

\(BEST\) 定理,套用完成后,由于每一个路径都对应了 \(deg_1\) 这么多的不同起始方向的情况数,乘上去就可以了。

Code

#include<bits/stdc++.h>

using namespace std;

inline void read (int&a)
{
    a = 0; char k = getchar(); int f = 1;
    while (k > '9' || k < '0') { if (k == '0') f = -1; k = getchar(); }
    while (k >= '0' && k <= '9') { a = a * 10 + k - '0'; k = getchar (); }
    a *= f;
}

const int N = 200 + 5, mod = 1000003;
inline int plu (int u, int v) { return u + v >= mod ? u + v - mod : u + v; }
inline int sub (int u, int v) { return u - v < 0 ? u - v + mod : u - v; }
inline int mul (int u, int v) { return 1LL * u * v % mod; }
int a[N][N], n, outdeg[N], indeg[N], fac[200000 + 5];

inline int Guass ()
{
//  for (int i = 1; i <= n; ++i, puts (""))
//      for (int j = 1; j <= n; ++j)
//          printf ("%d ", a[i][j]);
    int ans = 1;
    for (int i = 1; i <= n - 1; ++i)
    {
        for (int j = i + 1; j <= n - 1; ++j)
        {
            while (a[j][i])
            {
                int l = a[i][i] / a[j][i];
                for (int k = i; k <= n - 1; ++k)
                    a[i][k] = sub (a[i][k], mul (l, a[j][k]));
                swap (a[i], a[j]);
                ans = mod - ans;
            }
        }
        ans = mul (ans, a[i][i]);
    }
    return ans;
}

int main ()
{
    fac[0] = 1;
    for (int i = 1; i <= 200000; ++i)
        fac[i] = 1LL * fac[i - 1] * i % mod;
    while (scanf ("%d", &n) == 1 && n)
    {
        memset (a, 0, sizeof a);
        memset (outdeg, 0, sizeof outdeg);
        memset (indeg, 0, sizeof indeg);
        for (int i = 1; i <= n; ++i)
        {
            int s; read (s);
            for (int j = 1; j <= s; ++j)
            {
                int k; read (k);//i -> k
                a[i][k]--;
                a[i][i]++;
                indeg[k]++;
                outdeg[i]++;
            }
        }
        if (n == 1) { printf ("%d\n", fac[ indeg[1] ]); continue; }//不用特判也可以过
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                a[i][j] = sub (a[i][j], 0);
        bool flag = false;
        for (int i = 1; i <= n; ++i)
            if (indeg[i] != outdeg[i])
                { printf ("0\n"), flag = true; break; }
        if (flag) continue;
        int ans = 1;
        for (int i = 1; i <= n; ++i)
            ans = mul (ans, fac[ indeg[i] - 1 ]);
        ans = mul (ans, mul (Guass(), indeg[1]));
        printf ("%d\n", ans);
    }
    return 0;
}

Conclusion

又开始错各种细节了。

比如矩阵忘了去掉某一行,而是直接 \(n\) 行计算。

注意某一行我写了不用特判也可以,因为高斯消元里面返回的因该是 \(1\)

bzoj3659Which Dreamed It

标签:lag   void   bool   ret   flag   break   code   直接   names   

原文地址:https://www.cnblogs.com/ChiTongZ/p/11618446.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!