Choose and Divide UVa 10375

题目大意:给出p,q,r,s,求组合数C(p,q)/C(r,s)

题目思路:

化简得到:原式等价于(p!(r-s)!s!) / (r!(p-q)!q!)

由算数基本定理可知任意一个正整数可被唯一分解为素数幂乘积的形式,将分子分母分解后,进行约分即可。

为了避免计算过程数据移除,我们每计算分子的一项因子,就就算分母的一项因子进行约分

//#pragma GCC optimize(2)
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<stack>
#include<vector>
#include<math.h>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f

int vis[10005];
LL up[10005];
LL down[10005];
vector<LL> prime;

void Init()
{
    vis[1] = 1;
    for(LL i=2; i<10005; i++)
    {
        if(!vis[i])
        {
            prime.push_back(i);
            //vis[i] = 1;
            for(int j=i*2; j<10005; j+=i)
                vis[j] = 1;
        }
    }
}


LL bit[10005];

void Solve(LL num,int op)
{
    LL Size = prime.size();
    for(LL i=2; i<=num; i++)
    {
        LL temp = i;
        for(LL j=0; j<Size; j++)
        {
            LL p = prime[j];
            while(temp%p==0)
            {
                if(op==1)
                    bit[p]++;
                else
                    bit[p]--;
                temp/=p;
            }
            if(temp==1)
                break;
        }
    }
}

LL Pow(LL n,LL m)
{
    LL ans = 1;
    while(m)
    {
        if(m&1)
        {
            ans *= n;
        }
        n *= n;
        m /= 2;
    }
    return ans;
}

int main()
{
    Init();
    LL p,q,r,s;
    double a = 1, b = 1;
    while(cin>>p>>q>>r>>s)
    {
        memset(up,0,sizeof(up));
        memset(down,0,sizeof(down));
        memset(bit,0,sizeof(bit));
        a = 1;
        b = 1;
        Solve(p,1);
        Solve(r,-1);
        Solve(r-s,1);
        Solve(p-q,-1);
        Solve(s,1);
        Solve(q,-1);
        int Size = prime.size();
        for(int j=0; j<Size; j++)
        {
            int i = prime[j];
            a = a*pow(i,bit[i]);

        }
        printf("%.5f\n",a/b);
    }
    return 0;
}
View Code

 

posted @ 2019-05-03 12:22  声声醉如兰  阅读(208)  评论(0编辑  收藏  举报