题意:
已知C(m,n)=m! / (n!*(m-n!)),输入整数p,q,r,s(p>=q,r>=s,p,q,r,s<=10000),计算C(p,q)/C(r,s)。输出保证不超过10^8,保留5位小数
解法1:
根据唯一分解定理,N!可以分解为若干个质数相乘。
模拟分解这个式子
代码:
#include <bits/stdc++.h>
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);
}
int p,q,r,s;
void add_integer(int n,int d)
{
for(int i=0;i<primes.size();i++)
{
while(n%primes[i]==0)
{
n/=primes[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()
{
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++)
{
if(e[i]!=0)
ans*=pow(primes[i],e[i]);
}
printf("%.5lf\n",ans);
}
return 0;
}
解法2:
用组合公式,一边乘一边除即可,注意C(10,4)==C(10,6),这种类似情况我们求C(10,4)即可。
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int p,q,r,s;
double ans;
int t;
while(cin>>p>>q>>r>>s)
{
ans=1;
q=min(q,p-q);s=min(s,r-s);
t=max(q,s);
for(int i=1;i<=t;i++)
{
if(i<=q) {ans*=double(p-i+1)/double(i);}
if(i<=s) {ans/=double(r-i+1)/double(i);}
}
printf("%.5lf\n",ans);
}
return 0;
}