UVA10375 Choose and Divide (唯一分解定理)



题意:已知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位小数


解题思路:使用唯一分解定理进行求解


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>
#include<vector>
#include<algorithm>
#define CPY(A,B)memcpy(A,B,sizeof(A))
typedef long long LL;
typedef unsigned long long uLL;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
const LL INFF=0x3f3f3f3f3f3f3f3fLL;
const double EPS=1e-9;
const double OO=1e20;
const double PI=acos (-1.0);
int dx[]= {0,1,0,-1};
int dy[]= {1,0,-1,0};
int gcd (const LL &a,const LL &b) {return b==0?a:gcd (b,a%b);}
using namespace std;
const int MAXN=10000;
int Prime[MAXN],psize;
void INIT() {
    int m=sqrt (MAXN+0.5);
    memset (Prime,0,sizeof Prime);
    for (int i=2; i<=m; ++i) {
        if (!Prime[i]) {
            for (int j=i*i; j<=MAXN; j+=i) {
                Prime[j]=1;
            }
        }
    }
    psize=0;
    for (int i=2; i<MAXN; ++i) {
        if (!Prime[i]) {
            Prime[psize++]=i;
        }
    }
}
int e[MAXN];//当前结果的唯一分解式中各个素数的指数
void add_int (int n,int d) {
    for (int i=0; i<psize; ++i) {
        while (n%Prime[i]==0) {
            n/=Prime[i];
            e[i]+=d;
        }
        if (n==1) { break; }
    }
}
inline void add_f (int n,int d) {
    for (int i=1; i<=n; ++i) {
        add_int (i,d);
    }
}
//d=0表示乘,d=-1表示除
int main() {
    INIT();
    int p,q,r,s;
    while (scanf ("%d%d%d%d",&p,&q,&r,&s) !=EOF) {
        memset (e,0,sizeof e);
        add_f (p,1);
        add_f (q,-1);
        add_f (p-q,-1);
        add_f (r,-1);
        add_f (s,1);
        add_f (r-s,1);
        int maxn=max (p,r);
        double ans=1;
        for (int i=0; i<=maxn; ++i) {
            ans*=pow (Prime[i],e[i]);
        }
        printf ("%.5f\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值