zoukankan      html  css  js  c++  java
  • hdu5852 Intersection is not allowed! 【矩阵行列式】

    题意##

    给出(n*n)网格((n<=10^5))
    顶部有(K)个起点,底部有(K)个相对应的终点
    每次只能向下或向右走
    求有多少种从各个起点出发到达对应终点且路径不相交的路径?
    (10^9 + 7)取模

    题解

    按照组合数的套路
    二维空间从一个h * w的矩形左上角走到右下角只向下或向右走的方案数为(C_{h + w}^{h})

    这题直接求不好求,我们考虑容斥
    可以发现,如果两个路径相交,就相当于交换了终点
    那么我们枚举每个起点的终点,乘上一个容斥系数((-1)^t),其中(t)表示相交的路径个数,也可以看做选择的终点序列的逆序对个数

    按照每个起点择每一个终点构造出一个组合数的矩阵,按照矩阵的的定义你会发现其实答案就等于这个矩阵的行列式

    我们求一个行列式就做完了

    这题太神了

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 105,maxm = 200005,INF = 1000000000,P = 1000000007;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    LL fac[maxm],inv[maxm],fv[maxm];
    void init(){
    	fac[0] = 1;
    	for (int i = 1; i <= 200000; i++) fac[i] = fac[i - 1] * i % P;
    	inv[0] = inv[1] = 1;
    	for (int i = 2; i <= 200000; i++) inv[i] = (P - P / i) * inv[P % i] % P;
    	fv[0] = 1;
    	for (int i = 1; i <= 200000; i++) fv[i] = fv[i - 1] * inv[i] % P;
    }
    LL qpow(LL a,LL b){
    	LL ans = 1;
    	for (; b; b >>= 1,a = a * a % P)
    		if (b & 1) ans = ans * a % P;
    	return ans;
    }
    LL C(int n,int m){
    	if (m > n) return 0;
    	return fac[n] * fv[m] % P * fv[n - m] % P;
    }
    int n,K,a[maxn],b[maxn];
    LL A[maxn][maxn],ans;
    void gause(){
    	ans = 1;
    	for (int i = 1; i <= K; i++){
    		int pos = i;
    		while (A[pos][i] == 0 && pos <= K) pos++;
    		if (pos > K){ans = 0; return;}
    		if (pos != i) for (int j = i; j <= K; j++) swap(A[i][j],A[pos][j]),ans = -ans;
    		for (int j = i + 1; j <= K; j++){
    			LL t = A[j][i] * qpow(A[i][i],P - 2) % P;
    			for (int k = i; k <= K; k++)
    				A[j][k] = (A[j][k] - A[i][k] * t % P + P) % P;
    		}
    		ans = ans * A[i][i] % P;
    	}
    	ans = (ans % P + P) % P;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	init();
    	int T = read();
    	while (T--){
    		n = read(); K = read();
    		REP(i,K) a[i] = read();
    		REP(i,K) b[i] = read();
    		REP(i,K) REP(j,K) A[i][j] = C(n - 1 + b[j] - a[i],n - 1);
    		gause();
    		cout << ans << endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    动态生成 Excel 文件供浏览器下载的注意事项
    JavaEE 中无用技术之 JNDI
    CSDN 泄露用户密码给我们什么启示
    刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
    jQuery jqgrid 对含特殊字符 json 数据的 Java 处理方法
    一个 SQL 同时验证帐号是否存在、密码是否正确
    PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
    快速点评 Spring Struts Hibernate
    Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
    解决 jQuery 版本升级过程中出现 toLowerCase 错误 更改 doctype
  • 原文地址:https://www.cnblogs.com/Mychael/p/8869833.html
Copyright © 2011-2022 走看看