Description
某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。
分析
首先,我们知道:如果现在从(0, 0)点出发,只能沿着街道向正右方或者正上方行走时,到(n,m)点(n>=m)的方案数是Cmn+m。
发现,任何途径的点(x, y)都要满足x>=y就是不经过粉色线x=y+1
有一条违法的路径:
我们把路径按照粉色线做个对称,
我们发现,到橙色点的路径都一一对应每一条违法路径,也就是说,违法路径的方案数就是到橙色点的方案数。
所以,合法方案数=随便走的方案数-违法方案数=
Cmn+m
-
Cm−1n+m
注意:如果直接算可能会超时,要把式子简化,而且高精度要压位。
(转自http://blog.youkuaiyun.com/chen1352/article/details/51648846)
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
const int mo=10000;
int n,m,t,f[10000];
void cheng(int x)
{
int t=0;
for (int i=1;i<=f[0];i++)
{
f[i]=f[i]*x+t;
t=f[i]/mo;
f[i]=f[i]%mo;
}
if (t>0) f[++f[0]]=t;
}
void chu(int x)
{
int t=0;
for (int i=f[0];i>=1;i--)
{
int p=f[i]+t;
f[i]=p/x;
t=p%x*mo;
}
while (f[f[0]]==0 && f[0]>0) f[0]--;
}
void write()
{
printf("%d",f[f[0]]);
for (int i=f[0]-1;i>=1;i--)
{
int t=mo/10;
while (f[i]<t && t!=0)
{
printf("%d",0);
t/=10;
}
printf("%d",f[i]);
}
}
int main()
{
scanf("%d%d\n",&n,&m);
f[0]=1;
f[1]=n+1-m;
for (int i=n+2;i<=n+m;i++) cheng(i);
for (int i=2;i<=m;i++) chu(i);
write();
return 0;
}