Description
某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。
Solution
不能穿过 y=x 这条线,相当于不能碰到 y=x+1 这条线
然后我们取终点关于 y=x+1 对称的点。
可以发现,对于每条到对称点的路径,都碰到
y=x+1
,并且都能关于
y=x+1
对称出一条到终点的路径。
或者说,它们是一一对应的。
所以答案就是随便走到终点的路径-随便走到对称点的路径。
然后再用组合数高精度之类的搞搞就好了。
Code
高精度码量略大
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define mx 100000000
using namespace std;
struct arr
{
long long a[2500];
};
arr a,k;
int n,m;
arr pl(arr a,arr b)
{
int la,lb,lc,i;
arr c;
la=a.a[0];
lb=b.a[0];
memset(c.a,0,sizeof(c.a));
fo(i,1,max(la,lb))
{
c.a[i]=0;
c.a[i]=c.a[i]+a.a[i]+b.a[i];
c.a[i+1]=c.a[i]/mx;
c.a[i]=c.a[i]%mx;
}
lc=max(la,lb);
if (c.a[lc+1]!=0) lc++;
while(c.a[lc]==0&&lc>1) lc--;
c.a[0]=lc;
return c;
}
arr ti(arr a,int b)
{
int la,lc,i,j;
arr c;
la=a.a[0];
memset(c.a,0,sizeof(c.a));
j=0;
fo(i,1,la)
{
c.a[i]=j+a.a[i]*b;
j=c.a[i]/mx;
c.a[i]=c.a[i]%mx;
}
c.a[la+1]=j;
lc=a.a[0]+9;
while(c.a[lc]==0&&lc>1) lc--;
c.a[0]=lc;
return c;
}
arr t2(arr a,arr b)
{
int la,lb,lc,i,j;
arr c;
la=a.a[0];
lb=b.a[0];
memset(c.a,0,sizeof(c.a));
fo(i,1,lb)
{
fo(j,1,la)
{
c.a[i+j-1]=c.a[i+j-1]+b.a[i]*a.a[j];
c.a[i+j]=c.a[i+j]+c.a[i+j-1]/mx;
c.a[i+j-1]=c.a[i+j-1]%mx;
}
}
lc=la+lb-1;
if (c.a[lc+1]!=0) lc++;
while(c.a[lc]==0&&lc>1) lc--;
c.a[0]=lc;
return c;
}
int larger(arr a,arr b)
{
if (a.a[0]>b.a[0]) return 1;
if (a.a[0]<b.a[0]) return -1;
{
int i;
fod(i,a.a[0],1)
{
if (a.a[i]>b.a[i]) return 1;
if (a.a[i]<b.a[i]) return -1;
}
return 0;
}
}
arr div(arr a,int k)
{
int i,la=a.a[0];
fod(i,la,2)
{
if (a.a[i]%k!=0) a.a[i-1]+=(a.a[i]%k)*mx;
a.a[i]=a.a[i]/k;
}
a.a[1]=a.a[1]/k;
if (a.a[la]==0) a.a[0]--;
return a;
}
arr turn(int i)
{
int j;
arr c;
c.a[0]=floor(log(i)/log(mx))+1;
fo(j,1,c.a[0])
{
c.a[j]=i%mx;
i/=mx;
}
return c;
}
int main()
{
freopen("map.in","r",stdin);
int i;
cin>>n>>m;
a.a[0]=a.a[1]=1;
fo(i,n+2,n+m)
{
a=ti(a,i);
}
a=ti(a,n+1-m);
fo(i,2,m)
a=div(a,i);
fod(i,a.a[0],1)
{
int p=mx/10;
while(a.a[i]<p&&p>1&&i!=a.a[0])
{
printf("0");
p/=10;
}
printf("%d",a.a[i]);
}
cout<<endl;
}