Choose and Divide UVa10375 题解

  两个超大组合数相除。解法是分解质因数,用数组记录每个质因数称或除的次数,最后直接遍历数组计算即可

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
void Fact(int n, int opt, vector<int> primes, vector<int>& fact);
void addFact(int n, int opt, vector<int> primes, vector<int>& fact);
int main()
{
    int p, q, r, s;
    while (cin >> p >> q >> r >> s)
    {
        vector<int> nums(10001, 1);
        vector<int> primes(1);
        //获取1-10000的所有质数
        for (int i = 2; i <= 10000; ++i)
        {
            if (nums[i] == 1)
            {
                primes.push_back(i);
                for (int i1 = 1; i*i1 < 10000; ++i1)
                {
                    nums[i*i1] = 0;
                }
            }
        }
        vector<int> fact(primes.size(), 0);
        addFact(p, 1, primes, fact);
        addFact(q, -1, primes, fact);
        addFact(p - q, -1, primes, fact);
        addFact(r, -1, primes, fact);
        addFact(s, 1, primes, fact);
        addFact(r - s, 1, primes, fact);
        double answer = 1;
        for (int i = 1; i < fact.size(); ++i)
        {
            if (fact[i] != 0)
            {
                answer *= pow(primes[i], fact[i]);
            }
        }
        printf("%.5lf
", answer);
    }
    return 0;
}

void Fact(int n,int opt,vector<int> primes,vector<int>& fact)
{
    for (int i = 1; i < primes.size(); ++i)
    {
        while (!(n%primes[i]))
        {
            n = n / primes[i];
            fact[i]+=opt;
        }
        if (n == 1)
        {
            break;
        }
    }
}

void addFact(int n, int opt, vector<int> primes, vector<int>& fact)
{
    for (int i = 1; i <= n; ++i)
    {
        Fact(i, opt, primes, fact);
    }
}
View Code

  (用JAVA的大数好像直接算就可以而且不会超时)

原文地址:https://www.cnblogs.com/Algorithm-X/p/7522172.html