c语言线形筛素数,分解质因数 - osc_9fk93pk2的个人空间 - OSCHINA - 中文开源技术交流社区...

本文介绍了一种高效求解大组合数的方法,并针对模数非素数的情况给出了解决方案。此外,还提供了两种质因数分解算法:一种适用于频繁分解质因数的情况,另一种适用于待分解数较大或分解次数较少的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求卡特兰数 (其实就是组合数)

大组合数且模数非素数,无法求逆元

高精组合数,如果你不想打高精除的话(没人想打)

方法:

1

以求高精组合数为例

一般地,对于$n m \leq 10^6$ 可以打素数表,然后在mark i*prime[j]时附上标记prime[j]  其实就是i*prime[j] 的最小质因数,这样可以在分解时将复杂度控制在$O(logn)$以下。

b02b048d5a23969055108d8c76e7bdf10c4.jpg

e45e7efb681b739980ec5c6c2f83824e027.jpg

1 voidget_prime()2 {3 F(i,2,n)4 {5 if(!mark[i])6 {7 prime[++pc]=i;8 mark[i]=i;9 }10 F(j,1,pc)11 {12 if(i*prime[j]>n) break;13 mark[i*prime[j]]=prime[j];14 if(i%prime[j]==0) break;15 }16 }17 }

线性筛素数并标记

b4ea18a5f503fcd8ff4392c183f113f61b8.jpg

5158eb438cdb63ef7c409a27cfd73a69729.jpg

1 while(x!=1)2 {3 ++pz[mark[x]];4 x/=mark[x];5 }

对x分解质因数

同理对分母分解,然后我们只要--pz[]就可以了(组合数是整数,所以我们可以预见分母会被约掉)。

df7b7af0eacc29dcd061296c2b00d2c7d8c.jpg

78cf32fd2309e2dfa98c24e6a8e15680c9b.jpg

1 F(i,2,n) while(pz[i]--) dcheng(a,i);

高精乘低精

实际上pz[]有很多下标是无用的,我们可以让mark[]存素数的标号(即在prime[]中的下标)。这样在n m很大时可以减少上面代码的循环次数。

2

以下不是求组合数而单论分解。设x为要分解的数

对于x很大(1e9),我们可以用试除法。

枚举$1~\sqrt{x}$ 对于一个枚举到的i,除到不能整除为止,记录因数,显然这样得到的因数都是素数。

枚举完后,若x!=1 则将x加入质因子中。

这样做的正确性:反证法:假设有两个>sqrt(x)的质因数,那么将它们相乘会>x,与命题矛盾,得证。

然后我们就可以在$O(\sqrt{x})$下没有多开一个数组而愉快地解决了问题。

总结

两种算法比较:

1.对于要频繁分解质因数的情况,第一种更优。只要$O(n)$线性筛一遍,然后单次分解$O(logn)$。所以当估计操作数达到$O(\sqrt(n))$直接第一种

2.对于x很大,或分解次数很少的情况,第二种更优。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值