uva10375 Choose and Divide(唯一分解定理)
阿新 • • 發佈:2019-01-06
題意:已知C(m,n)=m! / (n!*(m-n!)),輸入整數p,q,r,s(p>=q,r>=s,p,q,r,s<=10000),計算C(p,q)/C(r,s)。輸出保證不超過10^8,保留5位小數
解題思路:
初步分析,本題時間上基本上沒有太大的限制,可以暴力求解C(m,n);
但是我們會發現C(10000,5000),早已超出了計算機整數的表示範圍,不過輸出保證了不超過10^8,所以本題
我們使用唯一分解定理進行求解,通過將其分解為指數冪次相乘的形式即可
原始碼:
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> using namespace std; const int MAXN=10000; int prime[MAXN+1]; int nprime; void getPrime(){ int m=sqrt(MAXN+0.5); memset(prime,0,sizeof(prime)); for(int i=2;i<=m;++i)if(!prime[i]) for(int j=i*i;j<=MAXN;j+=i) prime[j]=1; nprime=0; for(int i=2;i<=MAXN;++i){ if(!prime[i]) prime[nprime++]=i; } } int e[MAXN+1]; void add_integer(int n,int d){ for(int i=0;i<nprime;i++){ while(n%prime[i]==0){ n/=prime[i]; e[i]+=d; } if(n==1) break; } } void add_factorial(int n,int d){ for(int i=1;i<=n;i++) add_integer(i,d); } int main(){ getPrime(); int p,q,r,s; while(scanf("%d%d%d%d",&p,&q,&r,&s)!=EOF){ memset(e,0,sizeof(e)); add_factorial(p,1); add_factorial(q,-1); add_factorial(p-q,-1); add_factorial(r,-1); add_factorial(s,1); add_factorial(r-s,1); int maxn=max(p,r); double ans=1; for(int i=0;i<=maxn;i++){ ans*=pow(prime[i],e[i]); } printf("%.5lf\n",ans); } return 0; }