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

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ4031

    正解:矩阵树定理+高斯消元

    解题报告:

      矩阵树定理裸题,建图之后跑高斯消元。

      但是这道题比较特殊,取模取得是$10^9$,如果不用取模直接用$double$,取模质数的话就可以乘逆元,

      如果不是质数可能没有逆元,那么我们考虑我们的目的是要让之后的每一项的这一位都变成$0$,正好满足辗转相除法的最终结果,所以跑一遍辗转相除法就可以避开没有逆元的尴尬问题了。

      注意行列式交换一次会导致结果变号,所以记录一下,最后可能要取相反数。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    #include <bitset>
    using namespace std;
    typedef long long LL;
    typedef complex<double> C;
    const double pi = acos(-1);
    const int MAXN = 12;
    const int maxn = 100;
    const int mod = 1000000000;
    int n,m,cnt,b[MAXN][MAXN],D[maxn][maxn],G[maxn][maxn];//D:度数矩阵  G:邻接矩阵
    LL a[maxn][maxn],ans;
    char ch[MAXN][MAXN];
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void link(int x,int y){
    	G[x][y]=1;
    	D[x][x]++;
    }
    
    inline void Gauss(){
    	ans=1; int f=1;
    	for(int i=1;i<cnt;i++) {
    		for(int j=i+1;j<cnt;j++) {
    			LL x=a[i][i],y=a[j][i];
    			while(y) {
    				LL t=x/y; x%=y; swap(x,y);
    				for(int k=i;k<cnt;k++)
    					a[i][k]=(a[i][k]-t*a[j][k]%mod+mod)%mod;
    				for(int k=i;k<cnt;k++)
    					swap(a[i][k],a[j][k]);
    				f=-f;
    			}
    		}
    		if(a[i][i]==0) { ans=0; return ; }
    		ans=ans*a[i][i]%mod;
    	}
    
    	if(f==-1) ans=(mod-ans)%mod;
    }
    
    inline void work(){
    	n=getint(); m=getint(); int nowx,nowy;
    	for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(ch[i][j]=='.')
    				b[i][j]=++cnt;
    
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++) {
    			if(ch[i][j]=='*') continue;
    			for(int k=0;k<4;k++) {
    				nowx=i+dx[k]; nowy=j+dy[k];
    				if(nowx<=0 || nowy<=0 || nowx>n || nowy>m || ch[nowx][nowy]=='*') continue;
    				link(b[i][j],b[nowx][nowy]);
    			}
    		}
    
    	for(int i=1;i<=cnt;i++)
    		for(int j=1;j<=cnt;j++)
    			a[i][j]=D[i][j]-G[i][j],a[i][j]+=mod,a[i][j]%=mod;
    
    	Gauss();
    
    	printf("%lld",ans);
    }
    
    int main()
    {
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    jdbc-------JDBCUtil类 工具类
    jdbc --- javabean
    MapReduce 找出共同好友
    mapReducer 去重副的单词
    用户定义的java计数器
    mapReducer第一个例子WordCount
    win10 Java环境变量,hadoop 环境变量
    Writable序列化
    io 流操作hdfs
    [常用命令]OSX命令
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6523940.html
Copyright © 2011-2022 走看看