UVa-10375 Choose and divide 【唯一分解定理】

来源:互联网 发布:淘宝办签证怎么办理 编辑:程序博客网 时间:2024/05/22 15:33

本题如果直接暴力相乘的话会超范围。这一题用到了唯一分解定理。

概念:任意一个大于0的正整数都能被表示成若干个素数的乘积且表示方法是唯一的;整理可以将相同素数的合并;可以得到公式:n = P1^a1 * P2^a2 * …………* (P1 < P2 < ……Pn);

那么就可以先素数筛,然后用一个数组e存储第i个素数的指数。最后直接pow就可以了。这样就预先约掉了许多因子。

代码:

#include<stdio.h>#include<string.h>#include<math.h>#define MAX_N 10005int p,q,r,s,cnt;int e[MAX_N];int prime[MAX_N];bool is_prime[MAX_N+1];void sieve(int n){    cnt = 0;    memset(is_prime,true,sizeof(is_prime));    is_prime[0] = is_prime[1] = false;    for(int i = 2; i <= n; i++)    {        if(is_prime[i])            prime[cnt++] = i;        for(int j=0; j<cnt && prime[j]*i<=n; j++)        {            is_prime[prime[j]*i]=false;            if(i%prime[j]==0)   //关键点                break;        }    }}void add_integer(int n,int d){    for(int i=0;i<cnt;i++)    {        if(prime[i]>n) break;        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(){    sieve(MAX_N-1);    while(~scanf("%d%d%d%d",&p,&q,&r,&s))    {        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);        double ans=1;        for(int i=0;i<cnt;i++)        {            ans*=pow(prime[i],e[i]);        }        printf("%.5f\n",ans);    }    return 0;}
这一题还有一种简单解法,思路是乘的同时进行除,且需要取尽量小的运算次数。

代码:

#include<stdio.h>#include<string.h>int p,q,r,s;int main(){    while(~scanf("%d%d%d%d",&p,&q,&r,&s))    {        if(p-q<q) q=p-q;        if(r-s<s) s=r-s;        double ans=1;        for(int i=1;i<=q || i<=s;i++)        {            if(i<=q) ans=ans*(p-q+i)/i;            if(i<=s) ans=ans/(r-s+i)*i;        }        printf("%.5f\n",ans);    }    return 0;}




阅读全文
0 0
原创粉丝点击