1. 程式人生 > 實用技巧 >【高精度】加減乘+組合數+比較大小(結構體)

【高精度】加減乘+組合數+比較大小(結構體)

組合數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("\n"); } }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; } } }