高精+卡特兰数 bzoj3907网格

问题 A: 网格
时间限制: 1 Sec 内存限制: 256 MB
题目描述
【问题描述】
某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。
【输入格式】
输入文件中仅有一行,包含两个整数n和m,表示城市街区的规模。
【输出格式】
输出文件中仅有一个整数和一个换行/回车符,表示不同的方案总数。
【输入样例1】
6 6
【输出样例1】
132
【输入样例2】
5 3
【输出样例2】
28
【数据范围】
50%的数据中,n = m,
在另外的50%数据中,有30%的数据:1 <= m < n <= 100
100%的数据中,1 <= m <= n <= 5 000

结论就是C(n+m,n)-C(n+m,n+1)。
貌似是卡特兰数的基本证明。。。请去度娘找证明,我不会。→_→
剩下的只要搞一个高精即可。
有大佬重载了高精除。。。我。。因为一定是整数,所以我把分子分母强行约分,然后只做乘法,貌似也行。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#define N 50005
#define inf 10000
#define ll long long
using namespace std;
int read()
{
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
    return sum*f;
}
int n,m;
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
struct node
{
    int f[10005],s;
    node(){s=0;memset(f,0,sizeof(f));}
    friend node const operator+(node a,node b)
    {
        if(b.s>a.s)swap(a,b);
        int i;
        for(i=1;i<=a.s;i++)
        {
            a.f[i]+=b.f[i];
            if(a.f[i]>=inf)
            {
                a.f[i]-=inf;
                a.f[i+1]++;
            }
        }
        if(a.f[a.s+1]>0)a.s++;
        return a;
    }
    friend node const operator-(node a,node b)
    {
        for(int i=1;i<=a.s;i++)
        {
            a.f[i]-=b.f[i];
            if(a.f[i]<0)
            {
                a.f[i]+=inf;
                a.f[i+1]--;
            }
        }
        while(a.f[a.s]==0)a.s--;
        return a;
    }
    friend node const operator*(node a,int b)
    {
        int x=0,i;
        for(i=1;i<=a.s;i++)
        {
            a.f[i]*=b;a.f[i]+=x;
            x=a.f[i]/inf;
            a.f[i]%=inf;
        }
        if(x!=0)
        {
            a.s=i;a.f[i]+=x;
        }
        return a;
    }
};
int vis[10005],v[10005];
void hh(node x)
{
    printf("%d",x.f[x.s]);
    for(int i=x.s-1;i>0;i--)
        printf("%04d",x.f[i]);
    printf("\n");
}
void work()
{
    node sum,cnt;
    sum.s=1;sum.f[1]=1;
    cnt.s=1;cnt.f[1]=1;
    for(int i=2;i<=n;i++)vis[i]=i;
    for(int i=m+1;i<=m+n;i++)
    {
        v[i]=i;
        for(int j=2;j<=n;j++)
            if(vis[j]!=1)
            {
                int k=gcd(v[i],vis[j]);if(k==1)continue;
                v[i]/=k;vis[j]/=k;
                if(v[i]==1)break;
            }
    }
    for(int i=m+1;i<=m+n;i++)if(v[i]!=1)sum=sum*v[i];
    for(int i=2;i<=n+1;i++)vis[i]=i;
    for(int i=m;i<=m+n;i++)
    {
        v[i]=i;
        for(int j=2;j<=n+1;j++)
            if(vis[j]!=1)
            {
                int k=gcd(v[i],vis[j]);if(k==1)continue;
                v[i]/=k;vis[j]/=k;
                if(v[i]==1)break;
            }
    }
    for(int i=m;i<=m+n;i++)if(v[i]!=1)cnt=cnt*v[i];
    cnt=sum-cnt;
    hh(cnt);
}
int main()
{
    n=read();m=read();
    work();
}
posted @ 2017-10-06 20:19  Hzoi_QTY  阅读(243)  评论(0编辑  收藏  举报