zoukankan      html  css  js  c++  java
  • [bzoj4031][HEOI2015]小Z的房间

    在ditoly的帮助下搞懂了矩阵-树定理,想找一道题做做。spoj上有裸题,却翻不了墙,找了好久终于找到了bzoj上的一道 哈哈。

    --------------------------------------

    题目:给定一个矩阵,有一些格子是柱子,一些是房间。你可以打穿一些墙让相邻的房间可以联通,但是必须满足任意两个房间只有一条通路,求方案数量mod 。 n,m <=9

    题解:很裸的矩阵-树定理题目,但是模数不是质数,去看了一下题解,发现可以辗转相除,真的妙。

    #include<iostream>
    #include<cstdio>
    #define MN 100
    #define mod 1000000000LL
    #define eps 1e-8
    #define ll long long
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
     
    ll s[MN][MN];
    int n,m,tot=0,id[MN][MN];
    char st[MN][MN];
     
    ll gauss()
    {
        ll ans=1,mark=1;int i,j,k;
        for(int i=1;i<=tot;i++)
            for(int j=1;j<=tot;j++)
                if(s[i][j]<0)s[i][j]+=mod;
        for(i=1;i<=tot;i++)
        {
            for(j=i;j<=tot;j++)
                if(s[j][i]>eps)
                {
                    if(i!=j)
                    {
                        mark=-mark;
                        for(k=i;k<=tot;k++)
                            swap(s[i][k],s[j][k]);
                    }
                    break;
                }
            if(j>tot)continue;
            for(j=i+1;j<=tot;j++)
            {
                while(s[j][i])
                {
                    ll x=s[j][i]/s[i][i];
                    for(k=i;k<=tot;k++)
                        s[j][k]=(s[j][k]+mod-x*s[i][k]%mod)%mod;
                    if(!s[j][i]) break;
                    mark=-mark;
                    for(k=i;k<=tot;k++)
                        swap(s[j][k],s[i][k]);
                }
            }
        }
        for(int i=1;i<=tot;i++)
            ans=(ans*s[i][i]+mod)%mod;
        return mark==-1?(mod-ans)%mod:ans%mod;
    }
     
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            scanf("%s",st[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(st[i][j]=='.')
                    id[i][j]=++tot;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(st[i][j]=='.')
                {
                    if(i!=n&&st[i+1][j]=='.')
                    {
                        int a=id[i][j],b=id[i+1][j];
                        s[a][a]++;s[b][b]++;s[a][b]--;s[b][a]--;
                    }
                    if(j!=m&&st[i][j+1]=='.')
                    {
                        int a=id[i][j],b=id[i][j+1];
                        s[a][a]++;s[b][b]++;s[a][b]--;s[b][a]--;
                    }
                }
        tot--;
        printf("%lld",gauss());
        return 0;
    }
  • 相关阅读:
    Python-读取文件内容
    torch_03_二分类
    torch_02_多项式回归
    pytorch_01_基础_一维线性回归
    LC-KSVD 代码解读
    标签一致项(LC-KSVD)-全文解读
    PCA:主成分分析
    牛客刷题-大佬链接
    调试MATLAB代码
    scroll offset & client总结
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4031.html
Copyright © 2011-2022 走看看