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 ...
随机推荐
- linux下又一次定位svn url方法
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/oudahe/article/details/34437661 linux下又一次定位svn url方 ...
- Python之变量作用域
使用 global强制声明为全局变量
- go strconv
strconv是golang用来做数据类型转换的一个库. 介绍下strconv最常用的两个方法, 没有解释语言那么自在可以str(int),int(string), 那还算简练. num, err : ...
- Rendering Problems The following classes could not be found:- android.support.v7.internal.app.WindowDecorActionBar (Fix Build Path, Create Class)
如图出现如下的错误的时候,一般都是升级Androdi Studio 后导致的,引入库不全,或者其他 东西缺少 可以如下解决方案:
- OpenGL学习——自定义Shader工具类
从文件读取Vertex Shader 和 Fragment Shader的工具类. 代码如下: Shader.h #ifndef Shader_h #define Shader_h // GLEW # ...
- 深入理解zabbix(二)
深入理解zabbix(二) 链接:https://pan.baidu.com/s/1q5YwJMTcZLcS5OQ0iOu44A 提取码:8gdi 复制这段内容后打开百度网盘手机App,操作更方便哦 ...
- POJ-2888 Magic Bracelet(Burnside引理+矩阵优化+欧拉函数+逆元)
Burnside引理经典好题呀! 题解参考 https://blog.csdn.net/maxwei_wzj/article/details/73024349#commentBox 这位大佬的. 这题 ...
- 8、Python MySQL - mysql-connector 驱动
一. 在线安装 mysql-connector : pip install mysql-connector-python 二.操作流程 1.连接数据库信息: conn = mysql.connec ...
- PyCharm Change Font Size
file->settings->colors&fonts-> save as (save the current scheme as your own)-> font- ...
- mybatis中配置文件头
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...