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;
    }
    
    
  • 相关阅读:
    Linux开机自动启动ORACLE设置
    Linux Oracle服务启动&停止脚本与开机自启动
    日志挖掘(logminer)
    通过Oracle补充日志,找到锁阻塞源头的SQL
    Oracle Supplemental 补全日志介绍
    修改oracle系统参数spfile导致数据库无法启动解决
    ORA-10997:another startup/shutdown operation of this instance in progress解决方法
    Oracle DataBase单实例使用ASM案例(1)--ASM基本概念
    误删除数据文件,数据库还没有关闭
    2013全国电子设计竞赛进入国赛的项目总结
  • 原文地址:https://www.cnblogs.com/Mychael/p/8869833.html
Copyright © 2011-2022 走看看