zoukankan      html  css  js  c++  java
  • BZOJ 4031: [HEOI2015]小Z的房间 [矩阵树定理 行列式取模]

    http://www.lydsy.com/JudgeOnline/problem.php?id=4031


    裸题........

    问题在于模数是$10^9$

    我们发现消元的目的是让一个地方为0

    辗转相除法也可以做到这一点

    只不过取模用减整除来代替就好了

    注意本题需要分配$id$,因为柱子不能算

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=105,MOD=1e9;
    inline int read(){
        char c=getchar();int x=0;
        while(c<'0'||c>'9'){c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x;
    }
    int n,m,a[N][N];
    char s[11][11];
    void Gauss(int n){
        int s=0;
        for(int i=1;i<=n;i++){//printf("i %d
    ",i);
            int r=i;
            for(;r<=n;r++) if(a[r][i]) break;
            if(r==n+1){puts("0");return;}
            if(r!=i){
                s^=1;
                for(int k=i;k<=n;k++) swap(a[i][k],a[r][k]);
            }
            for(int j=i+1;j<=n;j++)
                while(a[j][i]){//printf("j %d %d
    ",j,a[j][i]);
                    ll t=a[j][i]/a[i][i];
                    for(int k=i;k<=n;k++) a[j][k]=(a[j][k]-t*a[i][k]%MOD+MOD)%MOD;
                    if(a[j][i]==0) break;
                    s^=1;
                    for(int k=i;k<=n;k++) swap(a[i][k],a[j][k]);
                }
        }
        ll ans=1;
        for(int i=1;i<=n;i++) ans=ans*a[i][i]%MOD;
        if(s) ans=(-ans+MOD)%MOD;
        printf("%lld",ans);
    }
    int id[N][N],tot;
    void buildEquation(){
        for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) if(s[i][j]=='.') id[i][j]=++tot;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++) if(id[i][j]){
                int u=id[i][j],v;
                if(i!=1&&s[i-1][j]=='.'){
                    v=id[i-1][j];
                    a[u][u]++;a[v][v]++;
                    a[u][v]--;a[v][u]--;
                }
                if(j!=1&&s[i][j-1]=='.'){
                    v=id[i][j-1];
                    a[u][u]++;a[v][v]++;
                    a[u][v]--;a[v][u]--;
                }
            }
        for(int i=1;i<=m*n;i++) for(int j=1;j<=m*n;j++) a[i][j]=(a[i][j]+MOD)%MOD;//printf("%d%c",a[i][j],j==n?'
    ':' ');
    }
    int main(){
        freopen("in","r",stdin);
        m=read();n=read();
        for(int i=1;i<=m;i++) scanf("%s",s[i]+1);
        buildEquation();//puts("hi");
        Gauss(tot-1);
    }
  • 相关阅读:
    开发中遇到的问题点
    ThreadLocal
    Java多线程10:join()方法
    Java多线程9:中断机制
    Java多线程8:wait()和notify()/notifyAll()
    Java多线程7:死锁
    Java多线程0:核心理论
    MySQL中and和or的优先级的问题
    Java多线程6:Synchronized锁代码块(this和任意对象)
    shiro英语
  • 原文地址:https://www.cnblogs.com/candy99/p/6421922.html
Copyright © 2011-2022 走看看