• 【高精度】加减乘+组合数+比较大小(结构体)


    组合数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;
            }
        }
    }
  • 相关阅读:
    spoj DQUERY
    省选模拟赛 爬山法
    bzoj1874 [BeiJing2009 WinterCamp]取石子游戏
    bzoj1013 [JSOI2008]球形空间产生器sphere
    省选模拟赛 让苍天知道我不认输(40分)
    省选模拟赛 厌世者打击(60分)
    省选模拟赛 至危警告
    bzoj4449 [Neerc2015]Distance on Triangulation
    省选模拟赛 cti
    数组、ArrayList、List、LinkedList的区别
  • 原文地址:https://www.cnblogs.com/HYDcn666/p/13504165.html
Copyright © 2020-2023  润新知