Choose and divide(唯一分解定理)

首先说一下什么是唯一分解定理

唯一分解定理:任何一个大于1的自然数N,如果N不是质数,那么N可以分解成有限个素数的乘积;例:N=(p1^a1)*(p2^a2)*(p3^a3)......其中p1<p2<p3......

所以当我们求两个很大的数相除时  唯一分解定理是一个不错的选择,不会爆范围

下面具体说一下怎么求唯一分解定理:

首先我们需要知道所有的素数:  用埃式算法打表求得:

void is_prime()
{
    cnt=0;
    for(int i=2;i<=maxn;i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            for(int j=i*2;j<=maxn;j+=i) vis[j]=true;
        }
    }
}

 

接下来 就是求pi和ai了,

void solve(ll n,ll d)
{
    for(int i=0;i<cnt;i++)
    {
        while(n%prime[i]==0)
        {
            n/=prime[i];
            e[i]+=d;
        }
        if(n==1) return ;
    }
}

 

下面看一道例题:

题目链接:https://vjudge.net/problem/UVA-10375

题目大意:用C(p,q)/C(r,s)  最后结果保留5位小数

思路:这道题不用唯一分解定理就不好做了,阶层相乘很有可能会爆数据范围,总之挺麻烦的,但是用唯一分解定理跟快就能A了  很简单  看代码应该就能明白了

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+5;
ll prime[maxn];
ll e[maxn];
bool vis[maxn];
ll cnt;
void is_prime()
{
    cnt=0;
    for(int i=2;i<=maxn;i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            for(int j=i*2;j<=maxn;j+=i) vis[j]=true;
        }
    }
}
void solve(ll n,ll d)//n为相乘的数 当为分子时d为1  为分母时d为-1   很好理解 对应指数+1或-1嘛
{
    for(int i=0;i<cnt;i++)
    {
        while(n%prime[i]==0)
        {
            n/=prime[i];
            e[i]+=d;
        }
        if(n==1) return ;
    }
}
int main()
{
    ll p,q,r,s;
    double ans;
    memset(vis,false,sizeof(vis));
    is_prime();
//    for(int i=0;i<cnt;i++) cout<<prime[i]<<" ";
//    cout<<endl;
    while(cin>>p>>q>>r>>s)
    {
        ans=1;
        memset(e,0,sizeof(e));
        for(int i=p;i>=1;i--) solve(i,1);
        for(int i=p-q;i>=1;i--) solve(i,-1);
        for(int i=q;i>=1;i--) solve(i,-1);
        for(int i=r-s;i>=1;i--) solve(i,1);
        for(int i=s;i>=1;i--) solve(i,1);
        for(int i=r;i>=1;i--) solve(i,-1);
        for(int i=0;i<cnt;i++)
            if(e[i]) ans*=pow(prime[i],e[i]);

        printf("%.5lf\n",ans);
    }
}

 

posted @ 2019-01-29 16:08  执||念  阅读(396)  评论(0编辑  收藏  举报