Choose and divide唯一分解定理/分解/直接 UVA

来源:互联网 发布:人工智能不会取代人类 编辑:程序博客网 时间:2024/05/22 11:41

题意:给你p,q,r,s
求:
C(p,q)/C(r,s);
p,q,r,s的范围在10000,然后结果在1e8.
看书,这里用到了唯一分解定理,其实就是让n!的因子尽量少,会有精度问题。然后不一定是质因子,但是质因子的时间比较短~
还有一种方法是直接除,因为c(p,q),它的分子分母的个数是一样的。

//唯一分解定理

#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#include <cstdio>#include <vector>using namespace std;const int maxn = 10005;int e[maxn];vector<int > prime;int vis[maxn];void make_prime(){    int k=(int)sqrt(10000)+1;    for(int i=2;i<=k;i++)    {        for(int j=i*i;j<=10000;j+=i)             vis[j]=1;       // printf("%d\n",i);}    }    for(int i=2;i<=10000;i++)        if(!vis[i]) prime.push_back(i);    return ;}void getadd(int ii,int n){    for(int i=0;i<prime.size();i++)    {        while(ii%prime[i]==0){            e[i]+=n;            ii=ii/prime[i];        }        if(ii==1) break;    }}void addg(int p,int n){    for(int i=1;i<=p;i++)    {        getadd(i,n);    }}int main(){    int p,q,r,s;    make_prime();    while(scanf("%d %d %d %d",&p,&q,&r,&s)!=EOF)    {        memset(e,0,sizeof(e));        addg(p,1);        addg(s,1);        addg(r-s,1);        addg(r,-1);        addg(q,-1);        addg(p-q,-1);        double ans=1;        for(int i=0;i<prime.size();i++)        {            if(e[i])            {               ans*=pow(prime[i],e[i]);            }        }        printf("%.5lf\n",ans);    }    return 0;}

//直接

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;#define dd doubleint main(){    int p,q,r,s;    while(scanf("%d %d %d %d",&p,&q,&r,&s)!=EOF)    {        double ans=1.0;        for(int i=1;i<=s||i<=q;i++)        {            if(i<=q)                ans*=(dd)(p-i+1)/i;            if(i<=s)            {                ans/=(dd)(r-i+1)/i;            }        }        printf("%.5f\n",ans);    }    return 0;}
阅读全文
0 0