LLL

题意:

求长度为两行,第一行 $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;
}
View Code
原文地址:https://www.cnblogs.com/lawyer/p/7774005.html