LGV定理 (CodeForces 348 D Turtles)/(牛客暑期多校第一场A Monotonic Matrix)
又是一个看起来神奇无比的东东,证明是不可能证明的,这辈子不可能看懂的,知道怎么用就行了,具体看wikihttps://en.wikipedia.org/wiki/Lindstr%C3%B6m%E2%80%93Gessel%E2%80%93Viennot_lemma
LGV定理就是求n个起点到n个终点(且一个起点对应一个终点)的不相交路径数目的一种方法,光看这句话不好理解,来看一道cf题
这道题给你一个n*m的矩阵(1~n, 1~m),现在有两只乌龟都从左上角(1,1)出发,到达右下角(n,m),乌龟每次只能往右或者往下走一格,且两只乌龟走的路径不能交叉,问一共有多少种走法。首先显然可知的是一只乌龟必然从(1,2)走到(n-1, m),另一只必然从(2,1)走到(n,m-1),这个画画图就知道很显然了,那么我们可以看作有两个2个起点,2个终点,问共多少种不相交路径,这就是LGV定理了。
LGV定理实际上是求一个行列式
ai是起点,bi是终点,e(ai, bj)代表从ai为起点到bj为终点的方法数目,特别的注意ai对应bi(就是我们想求的起点到终点的方案数)
那么对于这道题,就相当于求一个2x2行列式的值。
|e1, e2|
|e3, e4|
其中
e1 = a1(2,1)-->b1(n,m-1) 的方案数
e2 = a1(2,1)-->b2(n-1,m) 的方案数
这两个用一遍dp求出来
e3 = a2(1,2)-->b1n,m-1) 的方案数
e4 = a2(1,2)-->b2(n-1,m) 的方案数
这两个也用一遍dp求出来
然后只要代入行列式,就能求得a1-b1,a2-b2且路径不相交的方法数ans=(e1*e4-e2*e3)了
#include <iostream>
#include <string.h>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <math.h>
#include <string>
#include <algorithm>
#include <functional> #define SIGMA_SIZE 26
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x&-x)
#define foe(i, a, b) for(int i=a; i<=b; i++)
#define fo(i, a, b) for(int i=a; i<b; i++)
#define pii pair<int,int>
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL;
inline LL LMax(LL a, LL b) { return a>b ? a : b; }
inline LL LMin(LL a, LL b) { return a>b ? b : a; }
inline LL lgcd(LL a, LL b) { return b == ? a : lgcd(b, a%b); }
inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm
inline int Max(int a, int b) { return a>b ? a : b; }
inline int Min(int a, int b) { return a>b ? b : a; }
inline int gcd(int a, int b) { return b == ? a : gcd(b, a%b); }
inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = 1e9+;
const double eps = 1e-;
const int inf = 0x3f3f3f3f;
const int maxk = 3e6 + ;
const int maxn = 7e7 + ; bool g[][];
int row, col;
char str[];
LL dp[][]; void init()
{
cin >> row >> col; for (int i = ; i <= row; i++ )
{
scanf("%s", str+);
for ( int j = ; j <= col; j++ ) {
if (str[j]=='#')
g[i][j] = true;
}
}
} pair<LL, LL> getRoad(int x, int y)
{
memset(dp, , sizeof(dp));
dp[][] = ;
for (int i = x; i <= row; i++)
{
for (int j = y; j <= col; j++) {
if (!g[i][j])
dp[i][j] = (dp[i][j]+dp[i-][j]+dp[i][j-])%mod;
}
}
return make_pair(dp[row][col-], dp[row-][col]);
} int main()
{
init(); LL x1, x2, x3, x4;
pair<LL, LL> tmp; tmp = getRoad(, );
x1 = tmp.first; x2 = tmp.second;
tmp = getRoad(, );
x3 = tmp.first; x4 = tmp.second; LL ans = ((x1*x4)%mod-(x2*x3)%mod+mod)%mod;
printf("%lld\n", ans);
return ;
}
====================================分割线===============================================
========================================================================================
题目描述:
Count the number of n x m matrices A satisfying the following condition modulo (109+7).
* Ai, j ∈ {0, 1, 2} for all 1 ≤ i ≤ n, 1 ≤ j ≤ m.
* Ai, j ≤ Ai + 1, j for all 1 ≤ i < n, 1 ≤ j ≤ m.
* Ai, j ≤ Ai, j + 1 for all 1 ≤ i ≤ n, 1 ≤ j < m.
输入描述:
The input consists of several test cases and is terminated by end-of-file.Each test case contains two integers n and m.
输出描述:
For each test case, print an integer which denotes the result.
这道题就没这么裸了,我们考虑01分界线和12分界线,都可以看作是从(n,0)出发,到(0,m)的两条路,而且根据题意这两条路不能相交,是不是和LGV很像了呢?然而LGV定理中路线重合也算相交,在这道题中路线是可以重合的,比如如果没有1只有0和2,那么01和12分界线是完全重合的,然后这道题很神奇的操作就是把01分界线向左向上移动了一格,这样两条路必然不会重合了(画画图),而且也变成了两个起点两个终点,
a1 = (n-1, -1) a2 = (n, 0)
b1 = (-1, m-1) b2 = (0, m)
经过这个神奇的操作后就直接套用LGV就行了.....因为这题不像上一道CF路径中间有障碍,所以求方法数只要简单的用排列组合+阶乘逆元就行了(比如(n,0)--->(0,m),一共要走n+m步,其中选n步向上,选m步向右,就是算个组合数了)
#include <iostream>
#include <string.h>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <math.h>
#include <string>
#include <algorithm>
#include <functional> #define SIGMA_SIZE 26
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x&-x)
#define foe(i, a, b) for(int i=a; i<=b; i++)
#define fo(i, a, b) for(int i=a; i<b; i++)
#define pii pair<int,int>
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL;
inline LL LMax(LL a, LL b) { return a>b ? a : b; }
inline LL LMin(LL a, LL b) { return a>b ? b : a; }
inline LL lgcd(LL a, LL b) { return b == ? a : lgcd(b, a%b); }
inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm
inline int Max(int a, int b) { return a>b ? a : b; }
inline int Min(int a, int b) { return a>b ? b : a; }
inline int gcd(int a, int b) { return b == ? a : gcd(b, a%b); }
inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = 1e9+;
const double eps = 1e-;
const int inf = 0x3f3f3f3f;
const int maxk = 3e6 + ;
const int maxn = ; LL fac[maxn];
LL inv[maxn]; LL quickPow(LL a, LL b, LL m)
{
LL ans = , base = a;
while (b) {
if (b & )
ans = (ans*base) % m;
base = (base*base) % mod;
b >>= ;
}
return ans;
} void init()
{
fac[] = fac[] = ;
inv[] = inv[] = ; for( int i = ; i < maxn; i++ )
fac[i] = (fac[i-]*i) % mod; inv[maxn-] = quickPow(fac[maxn-], mod-,mod);
for( int i = maxn-; i >= ; i-- )
inv[i] = (inv[i+]*(i+)) % mod;
} LL C(int up, int down)
{
if (up > down) return ;
return fac[down]*inv[down-up]%mod*inv[up]%mod;
} //a1 = (n-1, -1) a2 = (n, 0)
//b1 = (-1, m-1) b2 = (0, m)
int main()
{
init();
int row, col;
while (~scanf("%d %d", &row, &col))
{
LL x1, x2, x3, x4;
x1 = C(row, row+col);
x2 = C(col+, row+col);
x3 = C(col-, row+col);
x4 = x1; LL ans = ((x1*x4)%mod - (x2*x3)%mod + mod) % mod;
printf("%lld\n", ans);
} return ;
}
LGV定理 (CodeForces 348 D Turtles)/(牛客暑期多校第一场A Monotonic Matrix)的更多相关文章
- 2019牛客暑期多校第一场题解ABCEFHJ
A.Equivalent Prefixes 传送门 题意:给你两个数组,求从第一个元素开始到第p个元素 满足任意区间值最小的元素下标相同的 p的最大值. 题解:我们可以从左往右记录到i为止每个区间的最 ...
- 2019 牛客暑期多校 第一场 H XOR (线性基)
题目:https://ac.nowcoder.com/acm/contest/881/H 题意:求一个集合内所有子集异或和为0的长度之和 思路:首先集合内异或和,这是线性基的一个明显标志,然后我们不管 ...
- 【2019牛客暑期多校第一场】E题ABBA
题目链接 大致题意 有(n+m)(n + m)(n+m)个字母A和(n+m)(n + m)(n+m)个字母B,组成一个长度为 2∗(n+m)2*(n + m)2∗(n+m)的字符串,并且使得字符串中有 ...
- 2019 牛客暑期多校 第二场 H Second Large Rectangle (单调栈)
题目:https://ac.nowcoder.com/acm/contest/882/H 题意:一个大的01矩阵,然后现在要求第二大的全一矩阵是多少 思路:在这里我们首先学习一下另一个东西,怎么求直方 ...
- 【牛客网多校第一场】A
题目链接:https://www.nowcoder.com/acm/contest/139/A 题意:大概就是给你0,1,2让你填矩阵问有多少种填法满足 a(i,j)<=a(i+1,j)以及a( ...
- 2018牛客多校第一场 A.Monotonic Matrix
题意: 给一个n*m的矩阵赋值(0,1,2).使得每个数都不小于它左面和上面的数. 题解: 构建0和1的轮廓线.对于单独的轮廓线,共需要往上走n步,往右走m步.有C(n+m,n)种方式. 两个轮廓线的 ...
- 牛客暑假多校第一场J-Different Integers
一.题目描述: 链接:https://www.nowcoder.com/acm/contest/139/JGiven a sequence of integers a1, a2, ..., an an ...
- 牛客暑假多校第一场 J Different Integers
题意:给你一个数组, q次询问, 每次询问都会有1个[l, r] 求 区间[1,l] 和 [r, n] 中 数字的种类是多少. 解法1, 莫队暴力: 代码: #include<bits/stdc ...
- 2019牛客暑期多校第二场题解FH
F.Partition problem 传送门 题意:有2n个人,分两组,每组n个,要求sum(vij)最大值. 题解:n并不大我们可以枚举每个人是在1组还是2组爆搜. 代码: #include &l ...
随机推荐
- POJ-1155 TELE 树形背包dp
dp[u][i]代表以u为根的子树选i个叶子的最大收益 那么dp[u][i]=max(dp[u][i],dp[v][k]+dp[u][i-k]-len) (1=<k<=i) 细节看代码: ...
- CSS文字超出省略
.ellipsis { white-space:nowrap overflow:hidden text-overflow:ellipsis }
- vue X-Template
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 文件上传绕过WAF
文件上传 文件上传实质上还是客户端的POST请求,消息主体是一些上传信息.前端上传页面需要指定 enctype为multipart/from-data才能正常上传文件. 此处不讲各种中间件解析漏洞只列 ...
- vue 多选框 checkbox 父到子传值
vue多选功能, 修改时选中的状态不能从当前组件中得到,从父组件中传过来. 这里 新增和修改封装了一个组件,在点击确定按钮后,会发送新增或修改请求,重新渲染页面.但是在点击[新增]/ [修改]按钮时, ...
- Java Http POST/GET 情求
POST: //返回体 public static final String RESPONCE_BODY = "responceBody"; //URL public static ...
- php linux下安装xml扩展
1.进入PHP安装源码包,找到ext下的ftp,进入 cd /home/local/php-5.6.25/ext/xml 2./usr/local/php/bin/phpize 3../configu ...
- Linux网卡驱动(4)—DM9000网卡驱动程序完全分析
1.硬件连接 mini2440开发板上DM9000的电气连接和mach-mini2440.c文件的关系 其中片选信号AEN使用了nGCS4,所以网卡的内存区域在BANK4,也就是从地址0x200000 ...
- 搭建hadoop集群 单机版
二.在Ubuntu下创建hadoop用户组和用户 这里考虑的是以后涉及到hadoop应用时,专门用该用户操作.用户组名和用户名都设为:hadoop.可以理解为该hadoop用户是属于一 ...
- linux安装jrockit 1.6
文章目录 下载 安装 配置环境变量 下载 https://download.csdn.net/download/wthn163/10631876?utm_source=bbsseo 安装 将.bin结 ...