zoukankan      html  css  js  c++  java
  • BZOJ3907网格

    这东西是拿Cat思想搞得组合数学。

    首先做这个需要会用网格法或折线法分析Cat的$C_{2n}^n-C_{2n}^{n-1}$是怎么来的。

    网格法:假如没有限制,从(0,0)到(n,n)的方案数为$C_{2n}^n$,就是一共有2n次操作位置(向右或向上),我们把向上走的操作插入这些位置即得上式,上面的黄线是当我们走到不合法情况时所碰到的第一条线,然后最终我们会走到(n,n)这个点,如果我们将矩形沿着这条线翻折,我们碰到黄线,然后走到(n,n)的走法,可以映射为碰到黄线,然后走到(n-1,n+1)的走法,因为对称嘛。

    而我们碰到黄线之前的走法在矩阵翻折中是不受影响的,这样,不合法方案数就是从(0,0)走到(n-1,n+1)的方案数,这个分析和上面差不多,总共$C_{2n}^{n-1}$种,全部的减去不合法的,就是合法的,$C_{2n}^n-C_{2n}^{n-1}$

    折线法:就是从(0,0)到(2n,0),每次只能沿y=x或y=-x走一个单位,最后图像整体没有位于x下方的部分的方案数。没有限制的话,总方案数为$C_{2n}^n$,因为可以把折线拆成2n段,那么有n段上扬,n段下跌。不能越过x轴,从第一次碰到y=-1这条线开始就不合法了,我们把这个点以后的折线沿y=-1翻折,由于最后到达(2n,0)点,翻折后就到达(2n,-2),此时问题转化为从(0,0)到(2n,-2)的方案数,有n段,n-1段上扬,n+1段下跌,方案数$C_{2n}^{n-1}$全部的减去不合法的,就是合法的,$C_{2n}^n-C_{2n}^{n-1}$

    那这个题就简单多了,同样用上面的方法,把一个n换成m就差不多了

    答案就是$C_{n+m}^n-C_{n+m}^{m-1}$,下面的代码是化简后的式子,没有高精减,高精除用唯一分解刚过去,而且时间复杂度也还好,就打的n√n的拆分,n的拆分(我自己证的,可能是假的)在下一篇博客里,(因为那个题√n拆过不去QAQ)。

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    using namespace std;
    int n,m;
    int prime[5000],prime_num;
    bool v[10050];
    int fz[5000],fm[5000];
    struct Bigint{
        int a[90000],len;
        void clear(){
            memset(a,0,sizeof(a));
            a[1]=1;
            len=1;
        }
        friend void operator * (Bigint &x,int y){
            int delta=0;
            for(int i=1;i<=x.len;i++){
                x.a[i]=x.a[i]*y+delta;
                delta=x.a[i]/10;
                x.a[i]%=10;
            }
            while(delta>0){
                x.a[++x.len]=delta%10;
                delta/=10;
            }
            while(x.a[x.len]==0&&x.len>1)
                x.len--;
        }
        void out(){
            for(int i=len;i>=1;i--)
                printf("%d",a[i]);
        }
    }ans;
    void doprime(){
        for(int i=2;i<=10005;i++){
            if(!v[i]) prime[++prime_num]=i;
            for(int j=1;j<=prime_num&&i*prime[j]<=10005;j++){
                v[i*prime[j]]=1;
                if(i%prime[j]==0) break;
            }
        }
    }
    void mulfz(int x){
        for(int i=1;i<=prime_num;i++)
            while(x%prime[i]==0){
                fz[i]++;
                x/=prime[i];
            }
    }
    void mulfm(int x){
        for(int i=1;i<=prime_num;i++)
            while(x%prime[i]==0){
                fm[i]++;
                x/=prime[i];
            }
    }
    int main(){
        scanf("%d%d",&n,&m);
        doprime();ans.clear();
        for(int i=2;i<=n+m;i++)
            mulfz(i);
        mulfz(n-m+1);
        for(int i=2;i<=m;i++)
            mulfm(i);
        for(int i=2;i<=n+1;i++)
            mulfm(i);
        /*for(int i=1;i<=prime_num;i++)
            cout<<prime[i]<<" ";cout<<endl;*/
        for(int i=1;i<=prime_num;i++){
            for(int j=1;j<=fz[i]-fm[i];j++)
                ans*prime[i];
        }
        ans.out();
        puts("");
        return 0;
    }
    View Code
  • 相关阅读:
    Springboot使用ehcache缓存
    Tomcat启用HTTPS协议配置过程
    细说document.ready和window.onload
    科技创新
    SpringBoot的ApplicationRunner
    禁用Chrome的“请停用以开发者模式运行的扩展程序”提示
    论文排版问题
    mathType换行等号对齐
    内部类调用外部类的成员,同名时怎么调用?
    Tomcat的manager app管理web项目
  • 原文地址:https://www.cnblogs.com/Yu-shi/p/11222174.html
Copyright © 2011-2022 走看看