题目概述
刚开始你在 (1,1) ,每次能够瞬间移动到右下任意一个格子(如下图),求到 (n,m) 的方案数。
解题报告
组合数很多性质我不知道啊QAQ,做到题目慢慢补吧。
∑i=0nCinCim=Cnn+m(n≤m)
证明:二项式定理: (a+b)n 中 akbn−k 的系数为 Ckn 。
那么 (a+b)n+m 中 anbm 的系数为 Cnn+m 。
(a+b)n(a+n)m 中 anbm 的系数为 ∑ni=0CinCm−im=∑ni=0CinCim 。
因为 (a+b)n(a+b)m=(a+b)n+m ,所以 ∑ni=0CinCim=Cnn+m(n≤m) 。
=====我是分割线QwQ=====
枚举步数
i
,我们可以把行列分开来考虑,那么就可以这么理解:有
这就变成了经典的盒子问题,假设
然后用上面说的公式就行了,答案为 Cn−2n+m−4 。
示例程序
#include<cstdio>
using namespace std;
typedef long long LL;
const int maxn=200000,MOD=1000000007;
int n,m,fac[maxn+5],INV[maxn+5];
bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;}
char readc()
{
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; else return *l++;
}
int readi(int &x)
{
int tot=0,f=1;char ch=readc(),lst=ch;
while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();}
if (lst=='-') f=-f;
while ('0'<=ch&&ch<='9') tot=(tot<<3)+(tot<<1)+ch-48,ch=readc();
return x=tot*f,Eoln(ch);
}
void Make()
{
fac[0]=INV[0]=INV[1]=1;
for (int i=1;i<=maxn;i++) fac[i]=(LL)fac[i-1]*i%MOD;
for (int i=2;i<=maxn;i++) INV[i]=MOD-(LL)INV[MOD%i]*(MOD/i)%MOD;
for (int i=2;i<=maxn;i++) INV[i]=(LL)INV[i]*INV[i-1]%MOD;
}
inline int C(int x,int y) {return (LL)fac[x]*INV[y]%MOD*INV[x-y]%MOD;}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
Make();while (readi(n),readi(m)!=EOF) printf("%d\n",C(n+m-4,n-2));
return 0;
}