AcWing 1315. 网格 (组合数的高精度运算、卡特兰数)

1315. 网格
首先利用推导卡特兰的方法,把所有不合法的路径,通过与 y = x + 1 y=x+1 y=x+1作对称变换。
终点就是 ( m − 1 , n + 1 ) (m-1,n+1) (m1,n+1),所以最终方案数就是 C ( n + m ) − C ( n + m , m − 1 ) C(n+m)-C(n+m,m-1) C(n+m)C(n+m,m1)

组合数的高精度计算步骤:

  • 线性筛素数
  • 质因数分解(阶乘的质因数分解)
  • 高精度乘法
  • 高精度减法
#include<stdio.h>
#include <iostream>
using namespace std;

// ans = C(n+m,n)-C(n+m,n+1)

const int N = 10010;
int primes[N], cnt = 0, s1[N], s2[N];
bool vis[N] = {
    
    0};

int r1[1000000] = {
    
    1}, len1 = 1;
int r2[1000000] = {
    
    1}, len2 = 1;
int ans[1000000];

int m,n;

// 欧拉筛素数
void get_primes(int n){
    
    
    for(int i=2;i<=n;i++){
    
    

        if(!vis[i]) {
    
    
            primes[cnt++] = i;
        }
        for(int j=0;j<cnt && primes[j]*i<=n;j++){
    
    
            vis[primes[j]*i] = 1;
            if(i%primes[j]==0) break;
        }
    }
}


// 求出 n!里面p的因子出现了多少次
int f(int n,int p){
    
    
    int res = 0;
    while(n){
    
    
        res += n/p;
        n /= p;
    }
    return res;
}

void getNumOfP(){
    
    
    for(int i=0;i<cnt;i++){
    
    
        s1[i] = f(n+m,primes[i]) - f(n,primes[i]) - f(m,primes[i]);
        s2[i] = f(n+m,primes[i]) - f(n+1,primes[i]) - f(m-1,primes[i]);
    }
}

// 高精度乘法
void mul(int a[],int b,int &len){
    
    
    int t = 0;
    for(int i=0;i<len;i++){
    
    
        t += a[i]*b;
        a[i] = t%10;
        t /= 10;
    }
    while(t){
    
    
        a[len++] =  t%10;
        t /= 10;
    }
}

void do_mul(){
    
    
    for(int i=0;i<cnt;i++){
    
    
        for(int j=0;j<s1[i];j++){
    
    

            mul(r1,primes[i],len1);
        }
    }

    for(int i=0;i<cnt;i++){
    
    
        for(int j=0;j<s2[i];j++){
    
    
            mul(r2,primes[i],len2);
        }
    }
}


// 高精度减法
void sub(){
    
    
    for(int i=0;i<=len1;i++){
    
    
        if(r1[i]<r2[i]){
    
    
            r1[i+1]--;
            r1[i] += 10;
        }
        ans[i] = r1[i]-r2[i];
    }
}

void printArray(){
    
    
    int pos = len1;
    while(pos>=0 && ans[pos]==0) pos--;
    while(pos>=0) printf("%d",ans[pos--]);
}

int main(){
    
    
    scanf("%d%d",&n,&m);
    get_primes(n+m);
    getNumOfP();
    do_mul();
    sub();
    printArray();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/108759960
今日推荐