[JZOJ3431]【GDOI2014模拟】网格

来源:互联网 发布:淘宝 i7主机 编辑:程序博客网 时间:2024/05/16 14:42

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 100000000using 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; }
0 0
原创粉丝点击