传送门:https://cn.vjudge.net/problem/UVA-10375
题意:
已知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)。输入保证不超过
,保留5位小数。
分析:
首先,求出10000以内的所有素数prime,然后用数组e表示当前结果的唯一分解式中各个素数的指数。例如,e={1,0,2,000,···}表示
。
以下代码中函数add_int(int n,int d)的作用是d=0时分解n,d=-1时分解1/n;add_fac(int n,int d)的作用是计算(n!)^d。
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
double qsm(double a,int b){
if(b<0)
return qsm((1.0/a),-b);
double res=1;
while(b){
if(b&1)
res*=a;
a*=a;
b>>=1;
}
return res;
}
const int N = 2e5 + 5;
bool isprime[N];
int cntp=0, prime[N/10], phi[N], e[N/10];
void init(){
memset(isprime, 1, sizeof(isprime));
isprime[0] = isprime[1] = 0; cntp = 0;
phi[1] = 1;
for(int i = 2; i < N; ++i){
if(isprime[i]){
prime[++cntp] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cntp && i * prime[j] < N; ++j){
isprime[i * prime[j]] = 0;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break ;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
void add_int(int n,int d){//d=0表示乘以n;d=-1表示除以n
for(int i=1;i<=cntp;i++){
while(n%prime[i]==0){
n/=prime[i];
e[i]+=d;
}
if(n==1) break;
}
}
void add_fac(int n,int d){//计算(n!)^d
for(int i=1;i<=n;i++)
add_int(i,d);
}
int main(){
init();
int p,q,r,s;
while(~scanf("%d%d%d%d",&p,&q,&r,&s)){
memset(e,0,sizeof(e));
add_fac(p,1);
add_fac(q,-1);
add_fac(p-q,-1);
add_fac(r,-1);
add_fac(s,1);
add_fac(r-s,1);
double ans=1;
for(int i=1;i<=cntp;i++)
ans*=qsm(prime[i],e[i]);
printf("%.5lf\n",ans);
}
return 0;
}