zoukankan      html  css  js  c++  java
  • 【高精度】加减乘+组合数+比较大小(结构体)

    组合数C

    1.最早的思路

    C如果用C(n,m)=n!/(m!(n-m)!),需要预处理阶乘,

    这样的话,会TLE+MLE(自行脑补)。

    2.暴力出奇迹

    既然阶乘不行,那我们回归暴力

    可以将阶乘枚举,然后分解质因数

    再用高精度乘法一个个处理,

    这样,就不需要什么除法了

    3.原理呢?

    还是这个式子:C(n,m)=n!/(m!(n-m)!)

    显然,由于组合数为正整数,

    所以所有的除数都会被抵消掉。

    分解质因数后,就可以抵消除数,

    那么我们就不需要除法了。

    struct node
    {
        int len;short s[5005];
        void wrt()
        {
            for(register int i=len-1;i>=0;i--)
            {
                printf("%ld",s[i]);
            }printf("
    ");
        }
    }ans;
    node sum(node x,node y)
    {
        node s;s.len=max(x.len,y.len)+2;
        for(register int i=0;i<=max(x.len,y.len)+3;i++)s.s[i]=0;
        int last=0;
        for(register int i=0;i<max(x.len,y.len);i++)
        {
            s.s[i]=(x.s[i]+y.s[i]+last)%10;
            last=(x.s[i]+y.s[i]+last)/10;
        }
        if(last)s.s[max(x.len,y.len)]=last;
        s.len=max(x.len,y.len)+2;
        while(s.s[s.len]==0)s.len--;
        s.len++;return s;
    }
    node times(node x,node y)
    {
        node c;
        c.len=0;
        for(int i=0;i<=(x.len+y.len)+2;i++)
        {
            c.s[i]=0;
        }
        for(int i=0;i<x.len;i++)
        {
            int last=0;
            for(int j=0;j<y.len;j++)
            {
                c.s[i+j]=c.s[i+j]+last+x.s[i]*y.s[j];
                last=c.s[i+j]/10;
                c.s[i+j]%=10;
            }
            c.s[i+y.len]+=last;
        }
        int lenc=(x.len+y.len)+2;
        while(c.s[lenc]==0)lenc--;
        lenc++;c.len=lenc;
        return c;
    }
    node make(int x)
    {
        node s;s.len=0;
        for(int i=1;i<=10;i++)s.s[i]=0;
        while(x)
        {
            s.s[s.len++]=x%10;
            x/=10;
        }
        return s;
    }
    node del(node x,node y)
    {
        node s;
        for(int i=0;i<max(x.len,y.len)+2;i++)s.s[i]=0;
        int last=0;
        for(int i=0;i<max(x.len,y.len);i++)
        {
            if(x.s[i]>=y.s[i]+last)
            {
                s.s[i]=x.s[i]-y.s[i]-last;
                last=0;
            }
            else
            {
                s.s[i]=10+x.s[i]-y.s[i]-last;
                last=1;
            }
        }
        s.len=max(x.len,y.len)+2;
        while(s.s[s.len]==0)s.len--;
        s.len++;
        return s;
    }
    bool check(node x,node y)
    {
        if(x.len>y.len)return 1;
        if(x.len<y.len)return 0;
        bool bz=0;
        for(int i=x.len-1;i>=0;i--)
        {
            if(x.s[i]>y.s[i]){bz=1;break;}
            if(x.s[i]<y.s[i]){bz=0;break;}
        }
        return bz;
    }
    void solve(int x,int k)
    {
        while(x>1)
        {
            num[to[x]]+=k;
            x/=to[x];
        }
    }
    node C(int m,int n)
    {
        x.len=0;for(int i=1;i<=5000;i++)x.s[i]=0;
        node s;s.len=1;s.s[0]=1;
        for(int i=1;i<=10000;i++)num[i]=0;
        for(int i=n-m+1;i<=n;i++)solve(i,1);
        for(int i=1;i<=m;i++)solve(i,-1);
        for(int i=1;i<=10000;i++)
        {
            node ber=make(i);
            for(int j=1;j<=num[i];j++)
            {
                s=times(s,ber);
            }
        }
        return s;
    }
    void pre()
    {
    for(int i=2;i<=10000;i++)
        {
            if(!to[i])
            {
                to[i]=i;
                pri[++pri[0]]=i;
            }
            for(int j=1;j<=pri[0];j++)
            {
                if(i*pri[j]>10000)break;
                to[i*pri[j]]=pri[j];
                if(i%pri[j]==0)break;
            }
        }
    }
  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/HYDcn666/p/13504165.html
Copyright © 2011-2022 走看看