1.题目描述:点击打开链接
2.解题思路:本题让计算两个组合数的商,既可以直接利用公式,也可以利用唯一分解定理:事先计算10000以内的所有素数,然后计算组合数分解后各个素数的幂,用数组e保存指数即可。这里计算指数时可以利用数论中求n!分解式中各个素因数指数的公式。
3.代码:
(利用唯一分解定理)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define maxn 10000+10
int vis[maxn];
int e[maxn];
vector<int>primes;
void init()//计算10000以内的素数
{
int m = sqrt(maxn + 0.5);
for (int i = 2; i <= m; i++)
if (!vis[i])
for (int j = i*i; j <= 10000; j += i)
vis[j] = 1;
for (int i = 2; i <= 10000; i++)
if (!vis[i])
primes.push_back(i);
}
void add_factorial(int n, int d)//计算指数并添加到数组e
{
int tmp = n;
for (int i = 0; i < primes.size(); i++)
{
if (n / primes[i] == 0)break;
int sum = 0;
int x = primes[i];
while (n / x>0)
{
sum += n / x;
x = x*primes[i];
}
if (d == 1)
e[i] += sum;
else
e[i] -= sum;
}
}
int main()
{
//freopen("test.txt", "r", stdin);
int p, q, r, s;
init();
while (cin >> 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 < primes.size(); i++)
ans *= pow(primes[i] , e[i]);
printf("%.5lf\n", ans);
}
return 0;
}
(利用公式直接计算)
#include <cstdio>
#include <algorithm>
using namespace std;
int main () {
int p, q, r, s;
while (scanf ("%d%d%d%d", &p, &q, &r, &s) != EOF) {
q = min (q, p - q);
s = min (s, r - s);
double ans = 1.0;
for (int i = 1; i <= q || i <= s; i++) {
if (i <= q)
ans = ans * (p - i + 1) / i;
if (i <= s)
ans = ans * i / (r - i + 1);
}
printf ("%.5lf\n", ans);
}
return 0;
}