题意:
求长度为两行,第一行 $m$ 个格子,第二行 $n$ 个格子的伪杨氏图表(只考虑左侧上侧单增的问题)个数$(n,m < 10^9)$ 取余 $10^9+7$。
解法:
将第一行考虑为左括号,第二行考虑为右括号,等价于括号序列问题。
考虑用经典方法将 $n times m$ 的方格路径中穿过 $x+y = n+m$ 的路径条数转化为 $(n+1) imes (m-1)$ 的方格路径条数
从而$ans = C_{n+m}^n - C_{n+m}^{n+1}$ 用 Lucas 定理后考虑打表求阶乘。
#include <bits/stdc++.h> #define LL long long #define LD double #define FOR(i,a,b) for (int i = (a);i <= (b); i++) #define DFOR(i,a,b) for (int i = (a);i >= (b); i--) #define debug(x) cerr << "debug: " << (#x) << " = " << (x) <<endl; #define PI acos(-1) #define mp make_pair #define pb push_back #define itr iterator #define bit(x) (1LL<<(x)) #define lb(x) ((x)&(-x)) #define sqr(x) ((x)*(x)) #define gn 3 #define l(x) ch[x][0] #define r(x) ch[x][1] #define y0 Y0 #define y1 Y1 #define y2 Y2 #define fir first #define sec second using namespace std; const int M = 10000000, P = 1000000007; int sab[] = {1,682498929,491101308,76479948,723816384,67347853,27368307,625544428,199888908 ,888050723,927880474,281863274,661224977,623534362,970055531,261384175,195888993,66404266,547665832,109838563,933245637,724691727, 368925948,268838846,136026497,112390913,135498044,217544623,419363534,500780548, 668123525,128487469,30977140,522049725,309058615,386027524,189239124,148528617,940567523,917084264,429277690, 996164327,358655417,568392357,780072518,462639908,275105629,909210595,99199382,703397904,733333339,97830135, 608823837,256141983,141827977,696628828,637939935,811575797,848924691,131772368,724464507,272814771,326159309,456152084,903466878, 92255682,769795511,373745190,606241871,825871994,957939114,435887178,852304035,663307737,375297772,217598709,624148346,671734977, 624500515,748510389,203191898,423951674,629786193,672850561,814362881,823845496,116667533,256473217,627655552,245795606, 586445753,172114298,193781724,778983779,83868974,315103615,965785236,492741665,377329025,847549272,698611116 }; LL qpow(LL x,int n) { LL ans=1; for(;n;n>>=1,x=x*x%P) if(n&1) ans=ans*x%P; return ans; } LL fac(int n) { LL t = n/M; LL ans = sab[t]; FOR(i,t*M+1,n) ans = 1ll*ans*i%P; return ans; } LL comb(int n,int m) { if(n<m) return 0; if(m==0) return 1; m = min(m,n-m); return fac(n)*qpow(fac(n-m)*fac(m)%P,P-2)%P; } LL Lucas(int n,int m) { if(m==0) return 1; return Lucas(n/P,m/P)*comb(n%P,m%P)%P; } int main() { int n,m; while(cin >> n >> m) { cout << (Lucas(n+m,m)-Lucas(n+m,m-1)+P)%P << endl; } return 0; }