• 【高精度】【组合数】


    1>矩阵取数

     简单dp+高精度

    今天新尝试了结构体写高精度

    //再写一个40位的高精度加法 
    //以及一个高精度乘法
    //我要写一个压缩成4位的!!! 
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m;
    const int N=83;
    int d[N];
    
    const int mod=10000;
    struct hp
    {
        int len,p[11];
        hp()//构造函数 
        {
            memset(p,0,sizeof(p));
            len=0;
        }
        void print()
        {
            printf("%d",p[len]);
            for(int i=len-1;i>0;i--)
            {
                if(!p[i])
                    printf("0000");
                else
                {
                    for(int k=10;k*p[i]<=mod;k*=10) printf("0");
                    printf("%d",p[i]);
                } 
            }
        }     
    }dp[N],bas[N],ans;
    hp operator + (const hp &a,const hp &b)
    {
        hp c;
        c.len =max(a.len ,b.len );
        int x=0;
        for(int i=1;i<=c.len ;i++)
        {
            c.p[i]=a.p[i] +b.p[i] +x;
            x=c.p[i] /mod;
            c.p[i] %=mod;
        }
        if(x) c.p[++c.len ] =x;
        return c;
    }
    hp operator *(const hp &a,const int &b)
    {
        hp c;
        c.len =a.len ;
        int x=0;
        for(int i=1;i<=c.len ;i++)
        {
            c.p[i]=a.p[i] *b +x;
            x=c.p[i] /mod;
            c.p[i] %=mod;
        }
        while(x)
            c.p[++c.len ] =x%mod,x/=mod;
        return c;
    }
    hp max(const hp &a,const hp &b)
    {
        if(a.len !=b.len )
            return a.len >b.len ?a :b;
        
        for(int i=a.len ;i;i--)
            if(a.p[i] !=b.p[i] )
                return a.p[i] >b.p[i] ?a :b;
        return a;
    }
    
    void prepare()
    {
        bas[0].p[++bas[0].len ] =1;
        for(int i=1;i<=m;i++)
            bas[i] =bas[i-1] *2;
    }
    void DP()
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++)
        {
            for(int j=i;j;j--)
                dp[j]=max(dp[j] + bas[i]*d[m-i+j+1] ,dp[j-1] + bas[i]*d[j]);
            dp[0] = dp[0] + bas[i]*d[m-i+1];
        }
        hp t=dp[0];
        for(int i=1;i<=m;i++) t= max(t,dp[i]);
        ans = ans+t;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        prepare();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                scanf("%d",&d[j]);
            DP();
        }
        
        ans.print() ;
        return 0;
    }

    2>hanoi双塔问题

    一个简单的2^(n+1)-2,求高精度结果

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    int n;
    
    const int mod=10000;
    struct hp
    {
        int len,p[30];
        hp()
        {
            memset(p,0,sizeof(p));
            len=0;
        }
        void print()
        {
            printf("%d",p[len]);
            for(int i=len-1;i>0;i--)
            {
                if(!p[i]) printf("0000");
                else
                {
                    for(int k=10;k*p[i]<=mod;k*=10) printf("0");
                    printf("%d",p[i]);
                }
            }
        }
    };
    hp operator * (const hp &a,int &b)
    {
        hp c;
        c.len =a.len ;
        int x=0;
        for(int i=1;i<=c.len ;i++)
        {
            c.p[i] =a.p[i] *b +x;
            x=c.p[i] /mod;
            c.p[i] %=mod;
        }
        while(x) 
            c.p[++c.len ] =x%mod,x/=mod;
        return c;
    }
    hp operator - (const hp &a,const int &b)
    {
        hp c=a;
        int pos=1;
        c.p[pos] -=b;
        while(c.p[pos] <0)
        {
            c.p[pos] +=mod; 
            c.p[++pos] --;
        }
        while(!c.p[c.len ] ) c.len --; 
        return c;
    }
    
    int main()
    {
        scanf("%d",&n);
        if(n<=25)
            printf("%d
    ",(1<<n+1)-2);
        else
        {
            hp ans;int t=2;
            ans.p[++ans.len ] =2;
            for(int i=1;i<=n;i++)
                ans= ans*t;
            ans=ans-2;
            ans.print() ;
        }
        
        return 0;
    } 

    3>组合数问题

    一道提高组,但是是绿色的题

    简简单单的一个递推+统一mod后计数,90

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define int long long
    using namespace std;
    int k,t;
    int n,m;
    const int N=2003;
    int c[N][N];
    
    void prepare()
    {
        c[0][0]=1;
        c[1][0]=c[1][1]=1;
        for(int i=2;i<=2000;i++)
        {
            c[i][0]=1;
            for(int j=1;j<=i;j++)
                c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
        }    
    }
    
    signed main()
    {
        scanf("%lld%lld",&t,&k);
        prepare();
        while(t--)
        {
            int ans=0;
            scanf("%d%d",&n,&m);
            for(int i=0;i<=n;i++)
                for(int j=min(m,i);j>=0;j--)
                    if(!c[i][j]) ans++;
            printf("%lld
    ",ans);
        }
        
        return 0;
    }

    然后......想不到最终优化居然是前缀和......

    int c[N][N],tr[N][N];
    //询问太多,树状数组不如前缀和 
    void prepare()
    {
        c[0][0]=1;
        c[1][0]=c[1][1]=1;
        for(int i=2;i<=2000;i++)
        {
            c[i][0]=1,c[i][i]=1;
            for(int j=1;j<i;j++)
            {
                c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
                if(!c[i][j]) tr[i][j]=1;
            }
        }    
        for(int i=2;i<=2000;i++)
            for(int j=1;j<=i;j++)
                tr[i][j]+=tr[i][j-1];
    }
    
    signed main()
    {
        scanf("%lld%lld",&t,&k);
        prepare();
        while(t--)
        {
            int ans=0;
            scanf("%lld%lld",&n,&m);
            for(int i=2;i<=n;i++)
                ans+=tr[i][min(i,m)];
            printf("%lld
    ",ans);
        }
        
        return 0;
    }

    4>2^k进制数

    我好粗心啊,碰到一大堆乘啊除啊的时候,

    忘了去估算最大的数组大小,不停的re一个点

    组合数验证保狗命

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int k,w;
    const int N=1000,mod=10000;
    struct hp
    {
        int len,p[60];
        hp()
        {
            memset(p,0,sizeof(p));
            len=0;
        }
    }c[N],ans;
    hp operator + (const hp &a,const hp &b)
    {
        hp d;
        d.len =max(a.len ,b.len );
        int x=0;
        for(int i=1;i<=d.len ;i++)
        {
            d.p[i] =a.p[i] +b.p[i] +x;
            x=d.p[i] /mod; 
            d.p[i] %=mod; 
        }
        if(x) d.p[++d.len ] =x;
        return d;
    }
    
    void print()
    {
        printf("%d",ans.p[ans.len ] );
        for(int i=ans.len -1;i>0;i--)
        {
            if(!ans.p[i] ) printf("0000");
            else 
            {
                for(int k=10;k*ans.p[i] <=mod;k*=10)
                    printf("0");
                printf("%d",ans.p[i] );
            }
        } 
    }
    void get_c(int k)
    {
        c[k].p[++c[k].len ] =1;
        for(int i=k-1;i;i--)
            c[i]=c[i-1]+c[i] ;
    }
    
    int main()
    {
        scanf("%d%d",&k,&w);
        c[0].p[++c[0].len ] =1;
        int n1=1<<k,c1=w%k,c2,tt=w/k;
        c1=n1-(1<<c1),c2=n1-2;
        for(int i=1;i<c1;i++) 
            get_c(i);
        for(int i=c1;i<=c2;i++)
        {
            get_c(i);
            if(tt<=i) ans= ans+ c[tt];//加验证保狗命 
        }
        get_c(c2+1);
        c1=2,c2=min(w/k,c2+1);
        for(int i=c1;i<=c2;i++)
            ans = ans +c[i];
        
        print();
        return 0;
    }

     5>凸多边形的划分

    一道区间dp,原本准备好好写思路

    后来我被高精度烦死了...

    高精x高精,高精+高精

    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cstring>
    using namespace std;
    int max(int a,int b)
    { return a>b ?a :b; }
    int n;
    char s[1500];
    
    const int N=53,mod=10000;
    struct hp
    {
        int len,p[300];
        hp()
        {
            len=1;
            memset(p,0,sizeof(p)); 
        }    
        void read()
        {
            scanf("%s",s);
            int l=strlen(s);
            for(int i=l-1,j=1;i>=0;i--,j*=10)
            {
                if(j>=mod) len++,j=1;
                p[len]=p[len]+(s[i]-'0')*j;
            }
        }
    }d[N],f[N][N];
    hp operator + (hp &a,hp &b)
    {
        hp c;
        c.len =max(a.len ,b.len );
        int x=0;
        for(int i=1;i<=c.len ;i++)
        {
            c.p[i] =a.p[i] +b.p[i] +x;
            x=c.p[i] /mod;
            c.p[i] %=mod;
        }
        while(x>0)
        {
            c.p[++c.len ] =x%mod;
            x/=mod;
        }
        return c;
    }
    hp operator * (hp &a,hp &b)
    {
        hp c;
        c.len =a.len +b.len -1;
        for(int i=1;i<=a.len ;i++)
            for(int j=1;j<=b.len ;j++)
                c.p[i+j-1] += a.p[i] *b.p[j] ;
        int x=0;
        for(int i=1;i<=c.len ;i++)
        {
            c.p[i] +=x;
            x=c.p[i] /mod;
            c.p[i] %=mod;
        }
        while(x>0)
        {
            c.p[++c.len ] =x%mod;
            x/=mod;
        }
        return c; 
    }
    hp min (hp &a,hp &b)
    {
        if(a.len !=b.len )
            return a.len<b.len ?a :b;
        for(int i=a.len ;i>0;i--)
            if(a.p[i] !=b.p[i] )
                return a.p[i]<b.p[i] ?a :b;
        return a;
    }
    
    void print()
    {
        printf("%d",f[1][n].p[f[1][n].len ] );
        for(int i=f[1][n].len -1;i>0;i--)
        {
            int t=f[1][n].p[i] ;
            if(!t ) printf("0000");
            else
            {
                for(int k=10;k*t<=mod ;k*=10) printf("0");
                printf("%d",t);
            }
        }
        printf("
    ");
    }
    
    int main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++) 
            d[i].read() ;
        
        for(int len=2;len<n;len++)
            for(int i=1,j=1+len; j<=n ;i++,j++)
            {
                hp t=d[i]*d[j];
                for(int k=i+1;k<j;k++)
                {
                    hp tt=f[i][k]+f[k][j];
                    hp ttt=t*d[k];
                    ttt= ttt+tt;
                    if(f[i][j].len >1 || f[i][j].p[1] >0 )
                    {
                        if(i==2 && j==5)
                        {
                            
                        }
                        f[i][j]=min(f[i][j], ttt );
                    }
                    else f[i][j]= ttt;
                }
            }
        
        print();
        return 0;
    }
  • 相关阅读:
    redis原理及实现
    RabbitMQ原理介绍
    我的mongoDb之旅(二)
    我的mongoDb之旅(一)
    PHP服务器Apache与Nginx的对比分析
    后端技术杂谈11:十分钟理解Kubernetes核心概念
    后端技术杂谈10:Docker 核心技术与实现原理
    后端技术杂谈9:先搞懂Docker核心概念吧
    后端技术杂谈8:OpenStack架构设计
    后端技术杂谈7:OpenStack的基石KVM
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11626868.html
Copyright © 2020-2023  润新知