• bzoj3659 Which dreamed it


    题目描述:

    n个房间,每个房间有若干把钥匙能够打开特定房间的门。

    你会做这么件事情:

    最初你在房间1。

    每当你到达一个房间,你可以选择该房间的一把钥匙,前往该钥匙对应的房间,并将该钥匙丢到垃圾桶中。

    你希望:最终回到房间1,且垃圾桶中有所有的钥匙。

    求方案数。两组方案不同,当且仅当使用钥匙的顺序不同。注意,每把钥匙都是不同的。

    题解:

    有个东西叫$BEST$定理。意思是一个有向图的欧拉回路数为生成数个数*$prod^{n}_{i=1}(deg[i]-1)!$。

    里面那个$deg$是入度或出度,反正一定相等。

    由于本题要求边序不同即可,所以答案要多乘一个$deg[1]$。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 105;
    const int MOD = 1000003;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,ind[N],otd[N],a[N][N];
    bool check()
    {
        for(int i=1;i<=n;i++)
            if(ind[i]!=otd[i])return 0;
        return 1;
    }
    ll fastpow(ll x,int y)
    {
        ll ret = 1ll;
        while(y)
        {
            if(y&1)ret=ret*x%MOD;
            x=x*x%MOD;
            y>>=1;
        }
        return ret;
    }
    ll ma_tr()
    {
        for(int i=1;i<n;i++)
            for(int j=1;j<n;j++)
                a[i][j]=(a[i][j]%MOD+MOD)%MOD;
        ll ret = ind[1];
    /*    for(int i=1;i<n;i++)
            for(int j=i+1;j<n;j++)
                while(a[j][i])
                {
                    ll d = a[i][i]/a[j][i];
                    if(d)for(int k=i;k<n;k++)
                    a[i][k]=(a[i][k]-d*a[j][k]%MOD+MOD)%MOD;
                    swap(a[i],a[j]);ret=-ret;
                }*/
        for(int i=1;i<n;i++)
            for(int j=i+1;j<n;j++)
                while(a[j][i])
                {
                    ll t = a[i][i]/a[j][i];
                    if(t)for(int k=i;k<n;k++)
                    a[i][k]=(a[i][k]-t*a[j][k]%MOD+MOD)%MOD;
                    swap(a[i],a[j]);ret=-ret;
                }
        for(int i=1;i<n;i++)
            ret=(ret*a[i][i]%MOD+MOD)%MOD;
        return ret;
    }
    int main()
    {
        while(1)
        {
            read(n);
            if(!n)break;
            memset(a,0,sizeof(a));
            memset(ind,0,sizeof(ind));
            memset(otd,0,sizeof(otd));
            for(int i=1;i<=n;i++)
            {
                read(otd[i]);a[i][i]=otd[i];
                for(int j=1,x;j<=otd[i];j++)
                {
                    read(x);
                    ind[x]++;
                    a[i][x]--;
                }
            }
            if(!check()){puts("0");continue;}
            ll ans = ma_tr();
            for(int i=1;i<=n;i++)
                for(int j=1;j<ind[i];j++)
                    ans=ans*j%MOD;
            printf("%lld
    ",ans%MOD);
        }
        return 0;
    }
  • 相关阅读:
    JavaScript自动化构建工具grunt、gulp、webpack介绍
    开始使用 Vuejs 2.0 ---简单总结2
    开始使用 Vuejs 2.0 ---简单总结1
    Bootboxjs快速制作Bootstrap的弹出框效果
    FlexSlider是一个非常出色的jQuery滑动切换插件
    CSS实现背景透明,文字不透明(兼容各浏览器)
    jquery中attr和prop的区别
    GitHub 的分支创建与合并
    [译]使用NuGet管理共享代码
    [译]Nuget.Server
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10386762.html
Copyright © 2020-2023  润新知