zoukankan      html  css  js  c++  java
  • BZOJ 3907: 网格 [Catalan数 高精度]

    3907: 网格

    Time Limit: 1 Sec  Memory Limit: 256 MB
    Submit: 402  Solved: 180
    [Submit][Status][Discuss]

    Description

    某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。

    Input

    输入文件中仅有一行,包含两个整数n和m,表示城市街区的规模。

    Output

    输出文件中仅有一个整数和一个换行/回车符,表示不同的方案总数。

    100%的数据中,1 <= m <= n <= 5 000

    你们出题人有意思吗,变式套上高精度又一道题.....
    问题在于我这个傻叉横纵坐标竟然搞混了
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e4+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m;
    bool notp[N];
    int p[N],lp[N];
    void sieve(int n){
        for(int i=2;i<=n;i++){
            if(!notp[i]) p[++p[0]]=i,lp[i]=p[0];
            for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
                notp[i*p[j]]=1;
                lp[i*p[j]]=j;
                if(i%p[j]==0) break;
            }
        }
    }
    struct Big{
        int d[N],l;
        Big():l(1){memset(d,0,sizeof(d));d[1]=1;}
        int& operator[](int x){return d[x];}
    }a,b;
    void Mul(Big &a,int b){
        int g=0;
        for(int i=1;i<=a.l;i++){
            g+=a[i]*b;
            a[i]=g%10;
            g/=10;
        }
        for(;g;g/=10) a[++a.l]=g%10;
    }
    void Minus(Big &a,Big &b){
        for(int i=1;i<=b.l;i++){
            if(a[i]<b[i]) a[i]+=10,a[i+1]--;
            a[i]-=b[i];
        }
        int p=b.l+1;
        while(a[p]<0) a[p]+=10,a[p+1]--;
        while(a[a.l]==0) a.l--;
    }
    void Print(Big &a){
        for(int i=a.l;i>=1;i--) printf("%d",a[i]);
    }
    
    int e[N];
    inline void add(int x,int d){
        while(x!=1){
            e[lp[x]]+=d;
            x/=p[lp[x]];
        }
    }
    void C(int n,int m,Big &ans){
        memset(e,0,sizeof(e));
        for(int i=n;i>=n-m+1;i--) add(i,1);
        for(int i=2;i<=m;i++) add(i,-1);
        for(int j=1;j<=p[0];j++) for(;e[j];e[j]--) Mul(ans,p[j]);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();m=read();
        sieve(n+m);
        C(n+m,n,a);
        C(n+m,n+1,b);
        Minus(a,b);
        Print(a);
    }
     
  • 相关阅读:
    return跳转 和 goto跳转
    continue跳转
    break跳转
    循环的嵌套,以for循环为例
    for“列表”型循环
    do while“直到”型循环
    while“当”型循环
    选择结构 switch
    Tomcat和Servlet简析
    并发事务和隔离级别
  • 原文地址:https://www.cnblogs.com/candy99/p/6407012.html
Copyright © 2011-2022 走看看