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

组合数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;
        }
    }
}
原文地址:https://www.cnblogs.com/HYDcn666/p/13504165.html