zoukankan      html  css  js  c++  java
  • 分解质因数

    • 求卡特兰数 (其实就是组合数)
    • 大组合数且模数非素数,无法求逆元
    • 高精组合数,如果你不想打高精除的话(没人想打)

    方法:

    1

    以求高精组合数为例

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

     1 void get_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 }
    线性筛素数并标记
    1 while(x!=1)
    2 {
    3     ++pz[mark[x]];
    4     x/=mark[x];
    5 }
    对x分解质因数

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

    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很大,或分解次数很少的情况,第二种更优。

  • 相关阅读:
    WordPress Editorial Calendar插件权限安全绕过漏洞
    Linux kernel 本地拒绝服务漏洞
    Linux kernel ‘evm_update_evmxattr’函数拒绝服务漏洞
    VB6-ListView的排序和点滴
    VB6IDE改造
    杂记-匆匆北京行
    第60篇随笔:《道法自然》读书笔记
    VB6 AddIns 控件样式模板
    VB6-改造ComUnit(免除用例名称注册)
    VB6-设计模式点滴
  • 原文地址:https://www.cnblogs.com/hzoi-yzh/p/11223690.html
Copyright © 2011-2022 走看看