首页 > 代码库 > UVA 10375 Choose and divide(唯一分解定理)

UVA 10375 Choose and divide(唯一分解定理)

这么大数的乘法、除法运算,肯定不能先全部乘起来,我的思路是计算出分子、分母上的每个数的个数(因为最大的数为10000,可以开一个数组记录个数)。

利用了随机数方法终于知道错在哪了,中间如果出现连乘还是会溢出,这点没想到,以下是我的溢出代码:

#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<time.h>
using namespace std;
int up[10005];
int main()
{
    srand(time(NULL));
//    freopen("out.txt","w",stdout);
    int p,q,r,s;
    while(cin>>p>>q>>r>>s)
    {

        memset(up,0,sizeof(up));
        double sum = 1;
        int t1 = r - s,t2 = p - q;
        for(int i = 2;i <= p;i++)
            up[i]++;
        for(int i = 2;i <= s;i++)
            up[i]++;
        for(int i = 2;i <= t1;i++)
            up[i]++;
        for(int i = 2;i <= q;i++)
            up[i]--;
        for(int i = 2;i <= r;i++)
            up[i]--;
        for(int i = 2;i <= t2;i++)
            up[i]--;
        for(int i = 2;i <= 10000;i++)
        {
            if(up[i] > 0) sum *= pow(i,up[i]);
            if(up[i] < 0) sum /= pow(i,-up[i]);
        }
        printf("%.5lf\n",sum);
    }
    return 0;
}

以下是我自己改的代码AC的,我强制要求乘法、除法交替运行:

#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<time.h>
using namespace std;
int up[10005];
int main()
{
//    freopen("out.txt","w",stdout);
    int p,q,r,s;
    while(cin>>p>>q>>r>>s)
    {
        int cheng = 2,chu = 2;
        memset(up,0,sizeof(up));
        double sum = 1;
        int t1 = r - s,t2 = p - q;
        for(int i = 2;i <= p;i++)
            up[i]++;
        for(int i = 2;i <= s;i++)
            up[i]++;
        for(int i = 2;i <= t1;i++)
            up[i]++;
        for(int i = 2;i <= q;i++)
            up[i]--;
        for(int i = 2;i <= r;i++)
            up[i]--;
        for(int i = 2;i <= t2;i++)
            up[i]--;
        while(1)
        {
            int flag = 1;
            for(int i = 2;i <=10000;i++)
                if(up[i]) {flag = 0;break;}
            if(flag) break;
            for(int i = cheng;i <= 10000;i++)  //乘法
                if(up[i] > 0)
                {
                    sum *= pow(i,up[i]);
                    up[i] = 0;
                    cheng = i + 1;
                    break;
                }
            for(int i = chu;i <= 10000;i++)  //除法
                if(up[i] < 0)
                {
                    sum /= pow(i,-up[i]);
                    up[i] = 0;
                    chu = i + 1;
                    break;
                }
        }
        printf("%.5lf\n",sum);
    }
    return 0;
}

LRJ的思路是先求出10000以内所有的素数,通过分解素数来计算,他的算法可以说比我的循环少很多,更不容易超时。