唯一分解定理

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

在做 UVA10375 时学到了这个算法,虽然自己理解的还不透彻,先把自己的看法写下来,日后再完善;

要用唯一分解定理第一步当然是素数打表了;之前素数打表一直用笨办法,翻了N多个题解后,看到了很多好的方法。记一下以备日后回顾用。

int primes[maxn+10],vis[maxn+10];
void getprimes()
{
    memset(vis,0,sizeof(vis));
    memset(primes,0,sizeof(primes));
    for(int i=2;i<=maxn;i++)
    {
        if(vis[i] == 0)
        {
            primes[len++] = i;
            for(int j=i*i;j <= maxn;j+=i)
                vis[j] = 1;
        }
    }
}

哈?!!第一眼表示真的没看懂,again 嗯懂了一点点,解释一下:

vis数组中0表示是素数,1表示不是素数。从第一个素数开始

2:2*2,  2*2+2,2*2+2+2.......

3:  3*3,3*3+3,3*3+3+3.......

后面的都不是素数,所以把这些都筛掉,然后把碰到的vis[i]为0的i存到primes中就可以了,这样就完成了素数打表。(至于为什么从i*i开始,还需请教各位大佬(感谢qq_16171157朋友的指教!!))(最后是vis数组表示有哪些素数)

memset(primes,0,sizeof(primes));
int m=sqrt(maxn+0.5),len=0;
for(int i=2; i<=m; i++)
{
    if(!primes[i])
    {
        for(int j=i*i;j <= maxn;j+=i)
        {
            primes[j] = 1;
        }
    }
}
for(int i=2;i <= maxn;i++)
{
    if(!primes[i])
        primes[len++]=i;
}

个人感觉这两种方法原理是一样的,第二种就只是少开了数组。

ok,打完表接下来就是进行分解了。

void add_integer(int n,int d)
{
    for(int i=0; i<len; i++)
    {
        while(n % primes[i] == 0)
        {
            n /= primes[i];
            e[i] += d;
        }
        if(n == 1)//提前结束,节约时间
            break;
    }
}

n是我们要分解的数字,当n在分子上的时候d为1,在分母上的时候d为-1;e数组表示的是i这个数能够分解成几个primes[i]相乘存的数值是primes[i]的次方。

double ans = 1;
for(int i=0; i <10000; i++)
{
     ans *= pow(primes[i],e[i]);
}

最后把这些数在相乘就可以了。

例如:

100经过分解之后得到的是

e[i]:           2 0 2

primes[i]:  2 3 5

相乘得2^2*5^2=100.(感谢Dawn-K指正错误!)

 

 

 

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值