【C/C++无聊练手(二)】将质因数分解封装为类+快速幂求幂模函数+代码正确性单元测试(本文作为下文的基础类)

本文介绍了使用C++编写质因数分解类Factor的实现过程,包括快速幂求幂模函数、PrimePow类以及Factor类的设计。文章详细阐述了每个类的功能、接口以及单元测试,旨在优化计算空间复杂度,支持大整数的质因数分解。

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

前言

在上篇文章【C/C++无聊练手(一)】从「计算1/N的循环节」到「计算M/N的循环节」的理论推导&代码实现中,我们对于 1 / N 1/N 1/N 循环节的问题实现了用 C/C++ 的计算。但在文末,笔者留下一个未解决的问题——

对于这个代码,其实我们还不够满意。因为只能计算千万级别的输入显然不够coooooool!我们希望挑战一个高难度任务,让我们能计算 1000000007 这种十亿级别的输入。不过我们会遇到一大困难——结果的长度有 1000000006 位,而我们代码的空间复杂度近似于 5 N 5N 5N ,常数 5 5 5 十分大。这使得我们在计算 1000000007 这种十亿级别的输入时,内存会被直接吃完。
下下篇文章中,我们将通过近世代数的理论,将代码的空间复杂度优化 N N N (事实上,可以优化到 N / 2 N/2 N/2 ,不过这样写起来麻烦些)。为了实现这样的优化,我们需要编写一个质因数分解的类,作为中间的辅助类,而这将放到下篇文章中进行

对于具体的优化方法,笔者暂且按下不表(其实就是根据欧拉定理进行优化),这部分内容将在后续的第三篇文章中提到。但笔者可以透露的是:本方法基于大量质因数分解。因此,笔者将质因数分解的代码封装为了类,放到本文单独介绍。

因为这部分代码较长,我也为每部分代码写了一个单元测试,以保证代码的正确性。

简短的理论介绍

根据算术基本定理,每个 ⩾ 2 \geqslant 2 2 的正整数都有唯一的质因数分解形式。例如 9828 = 2 2 × 3 3 × 7 1 × 1 3 1 9828 = 2^2\times 3^3\times 7^1\times 13^1 9828=22×33×71×131 。因此,我们可以将 2 2 ,   3 3 ,   7 1 ,   1 3 1 2^2,\ 3^3,\ 7^1,\ 13^1 22, 33, 71, 131 每个都看作元组 ( 2 , 2 ) ,   ( 3 , 3 ) ,   ( 7 , 1 ) ,   ( 13 , 1 ) \left(2,2\right),\ \left(3,3\right),\ \left(7,1\right),\ \left(13,1\right) (2,2), (3,3), (7,1), (13,1) ,用这 4 4 4 个元组来表示原正整数 9828 9828 9828 ,这一思想就是质因数分解。

根据我们问题需要,我们只需要对 [ 1 ,   2 32 ) \left[1,\ 2^{32}\right) [1, 232) 的整数进行质因数分解即可。我们知道:质数的个数是无限的。那么对于 [ 1 ,   2 32 ) \left[1,\ 2^{32}\right) [1, 232) 的整数,我们需要用无限的元组来存储它们的质因数分解吗?并不是!我们只需要 9 9 9 个元组就够了

其中的原理是——

2 × 3 × 5 × 7 × 11 × 13 × 17 × 23 × 29 < 2 32 2 × 3 × 5 × 7 × 11 × 13 × 17 × 23 × 29 × 31 > 2 32 (1.1) 2\times 3\times 5\times 7\times 11\times 13\times 17\times 23\times 29<2^{32}\\ 2\times 3\times 5\times 7\times 11\times 13\times 17\times 23\times 29\times 31>2^{32} \tag{1.1} 2×3×5×7×11×13×17×23×29<2322×3×5×7×11×13×17×23×29×31>232(1.1)

这里就不细讲了。

Factor.hpp头文件

将整个快速幂求幂模函数+质数的幂类+因式分解类打包成一个 Factor.hpp 文件,使得整个工程的逻辑更加清晰。

// Factor.hpp
#ifndef FACTOR_HPP
#define FACTOR_HPP

#include <iostream>
#include <cmath>                    // 用sqrt函数

typedef unsigned char      uint8;   // 使用uint8表示<256的正整数,用以节省空间
typedef unsigned long      uint32;  // 无符号32位整数
typedef unsigned long long uint64;  // 无符号64位整数

#define MAX8        (uint8) 255             // 2^8-1
#define MAX32       (uint32)4294967295      // 2^32-1
#define UNIT_TEST   0                       // 0: 不测试;1: 测试1;2: 测试1~2;3: 测试1~3;4: 测试1~4

/**
 * @brief 计算整数乘方,不做结果越界检查,请小心
 * @param base  底数,范围为uint32
 * @param pow   乘方,要求pow>0,因为pow<32,故用uint8
 *              因为pow通常很小,这里不采用快速幂
 */
uint32 MyPow (uint32 base, uint8 pow);

/**
 * @brief 计算(base^pow) % mod
 * @param base  底数(在本任务中,实际约定base=10)
 *              注意:要求该参数实际数据范围在uint32内!
 *              此处设置为uint64是为了防止溢出
 *              因为uint32 * uint32 < uint64
 * @param pow   乘方,一般是一个很大的数,所以要用快速幂
 * @param mod   模,一般是一个很大的数
 *              所以要求base和ans都用uint64储存,防止溢出
 */
uint32 MyPowMod (uint64 base, uint32 pow, uint32 mod);


/**
 * @brief PrimePow用于表示一个素数的m_prime的m_pow次幂。
 * 
 *        例如PrimePow(3, 5) == 3^5 == 243,m_pow不应当为0。
 *        本类主要作为质因数分解结果储存容器,不主动执行计算。
 */
class PrimePow {
private:
    uint32  m_prime;    // 素数
    uint8   m_pow;      // 该素数的幂

public:
    // 构造函数
    PrimePow() {};                  // 空构造,别删!
    PrimePow(uint32 prime, uint8 pow) : m_prime (prime)               // 赋值构造
                                      , m_pow   (pow) { }

    // 显示方法
    uint32 ToInt    ()      {return MyPow(m_prime, m_pow);}
    uint32 GetPrime ()      {return m_prime;}
    uint8  GetPow   ()      {return m_pow;}
    void   DispAll  ()      {std::cout << "(" << m_prime << "^" << (int)m_pow << ")";}

    // 操作接口(因为该接口由上层Factor控制,溢出检查由上层执行,此处不做溢出检查)
    /**
     * @brief 尝试乘以PrimePow类元素。
     *        乘成功返回1,自己prime小返回0,自己prime大返回2
     */
    uint8  TryMultiple (PrimePow pp);
    /**
     * @brief 尝试除以PrimePow类元素。
     *        除成功返回1,不匹配返回0,除完m_pow == 0返回2
     */
    uint8  TryDiv      (PrimePow pp);
};

/**
 * @brief Factor类是质因数分解类。
 * 
 *        构造时只是将N传入,不参与计算,要求N不等于0,注意N非负!
 *        调用Factorization()后执行质因数分解,结果储存在m_factor中
 */
class Factor {
private:        // 数据成员
    uint32      m_N;            // 整数本身,记为N
    PrimePow    m_factor[9];    // 存因式分解后的结果,因为2*3*5*7*11*13*17*23*29*31>2^32,所以长度为9就够了
    uint8       m_len;          // m_factor前m_len个元素才是有效的,初始m_len == 255代表未执行因式分解

protected:      // 这些函数用于TryMultiple和TryDiv调用,不应当直接调用,因为Insert和Del都不改变N
    
    bool       InsertPP      (PrimePow pp, uint8 pos);  // 尝试插入PrimePow因子到位置pos,超长返回false
    bool       DelPP         (uint8 pos);               // 尝试删除PrimePow因子,找不到返回false

public:
    // 构造对象(不进行因式分解)
    Factor()        {m_len = 255;}  // 空构造,别删!
    Factor(uint32 N);               // 只构造对象,不因式分解,N不能为0

    // 显示方法,参数获取接口
    void       DispFactor    ();    // 显示素因子形式,未执行Factorization()返回自身
    void       DispCalResult ();    // 显示N == 素因子形式
    uint32     GetN          () {return m_N;}
    uint8      GetLen        () {return m_len;}
    PrimePow   GetPP         (uint8  k) {return m_factor[k];}
    void       SetN          (uint32 N);

    // 操作接口
    void       Factorization ();                // 执行因式分解,结果储存到m_factor和m_len中
    bool       TryMultiple   (PrimePow pp);     // 尝试乘以PrimePow类元素,溢出返回false
    bool       TryDiv        (PrimePow pp);     // 尝试除以PrimePow类元素,不匹配返回false
    bool       TryMultiple   (Factor   ft);     // 尝试乘以Factor类元素,溢出返回false
    bool       TryDiv        (Factor   ft);     // 尝试除以Factor类元素,不匹配返回false
};

#if   UNIT_TEST >  0
void UnitTest();
#endif

#endif

准备工作1:求幂、求幂模函数

如果我们将一个数因式分解为了 125 = 5 3 125=5^3 125=53 ,我们得到了元组 ( 5 , 3 ) \left(5,3\right) (5,3) ,此时我们想根据元组计算这个数本身是什么,就应当使用 pow 函数求幂。虽然 C++cmath 库里给了 pow 函数,然而输出输出参数都是浮点数,并且考虑这里的幂次通常很小( < 32 <32 <32 ),没必要使用快速幂,所以我手动实现了一个 pow 函数

再考虑到我们在求方程的阶的时候经常用到 1 0 t ( m o d   N ) 10^{t} \left(\mathrm{mod}\ N\right) 10t(mod N) ,其中 t t t N N N 都可能很大,于是我们采用快速幂的方法来实现求幂模函数。

具体代码如下,具体各项参数类型的设置理由,我已经在 Factor.hpp 的注释里说得很详细了——

// Factor.cpp(part 1)
#include "Factor.hpp"

/****** MyPow|MyPowMod函数 ******/

uint32 MyPow (uint32 base, uint8 pow) {
    uint32 ans = base;

    for (uint8 i = 1; i < pow; ++i) {
        ans *= base;
    }
    return ans;
}

uint32 MyPowMod (uint64 base, uint32 pow, uint32 mod) {
    uint64 ans    = 1;

    while (pow > 0) {
        if (pow & 1) {      // if pow % 2 == 1
            ans = (ans * base) % mod;
        }
        base = (base * base) % mod;
        pow /= 2;
    }

    return (uint32)ans;
}

准备工作2:PrimePow类

我们定义一个名为 PrimePow 的类来储存质因数,其中有 m_primem_pow 两个成员,分别表示底数和幂次。该类配备有各种显示函数,还有 TryMultipleTryDiv 两个函数接口,以供上层的 Factor 类调用。

具体类的定义见 Factor.hpp ,大部分函数已经内联实现,只有两个函数在 Factor.cpp 里实现——

// Factor.cpp(part 2)
#include "Factor.hpp"

/****** PrimePow 类 ******/

uint8 PrimePow::TryMultiple (PrimePow pp) {
    if (m_prime == pp.GetPrime()) {
        m_pow += pp.GetPow();
        return 1;
    }
    else if (m_prime < pp.GetPrime()) {     // 底数不匹配则返回0或者2
        return 0;
    }
    else {
        return 2;
    }
}

uint8 PrimePow::TryDiv (PrimePow pp) {
    // 底数不匹配或被除数的pow比除数的pow小则返回false
    if (m_prime != pp.GetPrime() || m_pow < pp.GetPow()) {
        return 0;
    }
    else {  // 注意:此处返回2表示m_pow == 0,此时上层类应当主动删掉该节点
        m_pow -= pp.GetPow();
        return (m_pow == 0 ? 2 : 1);
    }
}

准备工作3:Factor类

我们定义一个名为 Factor 的类来储存质因数,其中有 m_NPrimePow[9]m_len 三个成员, m_N 就是记录下输入参数 Nm_len 记录 PrimePow[9] 中有多少个是有效的。

我们引入了 InsertPPDelPP 两个保护类成员,它们不应当被类外调用,因为它们只对 PrimePow[9]m_len 执行操作,不会对 m_N 执行操作,所以只应当被上层的 TryMultipleTryDiv 调用。

其余公有显示接口不必多说,主要提一下操作接口。我们构造一个 Factor 类的对象时,并不会执行质因数分解,只有在执行了 Factorization() 才会执行质因数分解。同时,如果只想把这个库用于质因数分解使用,可以调用 SetN 接口,从而不必反复构造该类的对象。

整个类的接口的调用层次是 Factor::TryDiv(Factor) --> Factor::TryDiv(PrimePow) --> PrimePow::TryDiv(PrimePow)

// Factor.cpp(part 3)
#include "Factor.hpp"

/****** Factor 类 ******/

Factor::Factor (uint32 N) {
    // 实际上,负数也不应当被放入Factor类,因为只是我自己用这个库,所以就没管这个事情了
    try {
        if (N == 0)                         // 异常处理
            throw -1;
    }
    catch (int errNum) {
        std::cout << "0不应当作为Factor类的参数,错误!" << std::endl;
    }

    m_N   = N;
    m_len = 255;                // m_len == 255代表未进行因式分解
}

void Factor::SetN (uint32 N) {
    // 实际上,负数也不应当被放入Factor类,因为只是我自己用这个库,所以就没管这个事情了
    try {
        if (N == 0)                         // 异常处理
            throw -1;
    }
    catch (int errNum) {
        std::cout << "0不应当作为Factor类的参数,错误!" << std::endl;
    }

    m_N   = N;
    m_len = 255;                // m_len == 255代表未进行因式分解
}

void Factor::DispFactor () {
    if (m_len == 255) {       // 如果还没执行Factorization(),则返回自身
        std::cout << m_N << "(尚未执行质因数分解)" << std::endl;
        return;
    }
    for (int i = 0; i < m_len; i++) {
        m_factor[i].DispAll();
    }
    std::cout << std::endl;
}

void Factor::DispCalResult () {
    std::cout << m_N << " = ";
    DispFactor();
}


void Factor::Factorization () {
    uint32  N       = m_N;
    uint32  sqrtN   = sqrt(N);
    uint8   counter = 0;

    m_len = 0;                          // 初始化m_len

    while (N % 2 == 0) {                // 单独算2
        N /= 2;
        ++counter;
    }
    if (counter != 0) {
        m_factor[m_len] = PrimePow(2, counter);     // k^counter
        sqrtN = sqrt(N);
        ++m_len;
    }

    counter = 0;
    for (uint32 k = 3;k <= sqrtN;k += 2) {  // 只判断奇数
        if (N % k == 0) {               // 如果k是因子
            while (N % k == 0) {
                N /= k;
                ++counter;
            }
            m_factor[m_len] = PrimePow(k, counter);     // k^counter
            sqrtN = sqrt(N);
            ++m_len;
            counter = 0;
        }
    }
    if (N != 1) {                       // 如果N不能整除sqrt(N)及以下的数,那么N是素数
        m_factor[m_len] = PrimePow(N, 1);
        ++m_len;
    }
}


bool Factor::InsertPP (PrimePow pp, uint8 pos) {
    if (m_len == MAX8) {
        std::cout << "未执行Factorization()不能对" << m_N << "进行InsertPP()" << std::endl;
        return false;
    }
    if (m_len >= 9 || pos > m_len) {
        std::cout << "InsertPP()执行错误,m_len=" << m_len << ", pos=" << pos << std::endl;
        return false;
    }
    for (int k = m_len - 1;k >= pos;--k) {      // 这里要一定int k!不然pos=0就死循环了
        m_factor[k + 1] = m_factor[k];  // 右移
    }
    ++m_len;
    m_factor[pos] = pp;
    return true;
}


bool Factor::DelPP (uint8 pos) {
    if (m_len == MAX8) {
        std::cout << "未执行Factorization()不能对" << m_N << "进行DelPP()" << std::endl;
        return false;
    }
    if (m_len == 0 || pos > m_len) {
        std::cout << "DelPP()执行错误,m_len=" << m_len << ", pos=" << pos << std::endl;
        return false;
    }
    for (uint8 k = pos + 1;k < m_len;++k) {
        m_factor[k - 1] = m_factor[k];  // 左移
    }
    --m_len;
    return true;
}


bool Factor::TryMultiple (PrimePow pp) {
    uint8 multState;
    
    if ((uint64)m_N * (uint64)pp.ToInt() > MAX32) { // 溢出
        std::cout << "TryMultiple(pp)乘法溢出,N=" << m_N << ", pp.toInt=" << pp.ToInt() << std::endl;
        return false;
    }
    
    m_N *= pp.ToInt();
    for (uint8 k = 0;k < m_len;++k) {
        multState = m_factor[k].TryMultiple(pp);
        if (multState == 1) {       // 乘法成功
            return true;
        }
        else if (multState == 2) {  // 自己的prime > pp的prime,应当插入
            return InsertPP(pp, k);
        }
    }
    return InsertPP(pp, m_len);     // 所有因子都比pp小,插入到最后
}


bool Factor::TryDiv (PrimePow pp) {
    uint8 multState;

    for (uint8 k = 0;k < m_len;++k) {
        multState = m_factor[k].TryDiv(pp);
        if (multState == 1) {       // 除法成功
            m_N /= pp.ToInt();
            return true;
        }
        else if (multState == 2) {  // 除完m_pow为0,删掉该因子
            m_N /= pp.ToInt();
            return DelPP(k);
        }
    }

    std::cout << "TryDiv(pp)除法执行失败,N=" << m_N << ", pp.toInt=" << pp.ToInt() << std::endl;
    return false;
}

bool Factor::TryMultiple (Factor ft) {
    if ((uint64)m_N * (uint64)ft.GetN() > MAX32) { // 溢出
        std::cout << "TryMultiple(ft)乘法溢出,N=" << m_N << ", ft.m_N=" << ft.GetN() << std::endl;
        return false;
    }
    for (uint8 k = 0;k < ft.GetLen();++k) {
        // 尝试乘法,如果第k次乘法失败,那么把之前的都除回去
        if (!TryMultiple(ft.GetPP(k))) {
            for (uint8 j = 0;j < k;++j) {
                TryDiv(ft.GetPP(j));
            }
            return false;
        }
    }
    return true;
}

bool Factor::TryDiv (Factor ft) {
    if ((uint64)m_N % (uint64)ft.GetN() != 0) { // 不匹配
        std::cout << "TryDiv(ft)除法溢出,N=" << m_N << ", ft.m_N=" << ft.GetN() << std::endl;
        return false;
    }
    for (uint8 k = 0;k < ft.GetLen();++k) {
        // 尝试除法,如果第k次除法失败,那么把之前的都乘回去
        if (!TryDiv(ft.GetPP(k))) { 
            for (uint8 j = 0;j < k;++j) {
                TryMultiple(ft.GetPP(j));
            }
            return false;
        }
    }
    return true;
}

正片:合并到一起进行单元测试——质因数分解类

上面写了这么长的代码,如何保证它们的正确性呢?我们在 Factor.cpp 代码加入如下单元测试代码,并将 Factor.hpp#define UNIT_TEST 0 改为 #define UNIT_TEST 4 ,准备执行单元测试——

// Factor.cpp(part 4)
#if   UNIT_TEST >  0
void UnitTest() {
#if   UNIT_TEST >= 1
    std::cout << "unit test1: uint32 MyPow (uint32 base, uint8 pow);" <<std::endl;
    std::cout << MyPow(2, 31) << std::endl;         // expected: 2147483648
    std::cout << MyPow(3, 20) << std::endl;         // expected: 3486784401
    std::cout << MyPow(7, 10) << std::endl;         // expected: 282475249
    std::cout << MyPow(5, 1)  << std::endl;         // expected: 5
#endif
#if UNIT_TEST >= 2
    std::cout << "unit test2: uint32 MyPowMod (uint64 base, uint32 pow, uint32 mod);" <<std::endl;
    std::cout << MyPowMod(MAX32-2, 114514, MAX32)   << std::endl;   // expected: 262144
    std::cout << MyPowMod(10,      114514, 1919810) << std::endl;   // expected: 1199790
    std::cout << MyPowMod(114514,  1926,   817)     << std::endl;   // expected: 723
    std::cout << MyPowMod(13,      8,      1024)    << std::endl;   // expected: 33
    std::cout << MyPowMod(2,       31,     MAX32)   << std::endl;   // expected: 2147483648
    std::cout << MyPowMod(3,       20,     MAX32)   << std::endl;   // expected: 3486784401
    std::cout << MyPowMod(7,       10,     MAX32)   << std::endl;   // expected: 282475249
    std::cout << MyPowMod(5,       1,      MAX32)   << std::endl;   // expected: 5
#endif
#if UNIT_TEST >= 3
    std::cout << "unit test3: PrimePow" << std::endl;
    PrimePow    pp1(5, 2);
    PrimePow    pp2(5, 3);
    PrimePow    pp3(3, 2);
    pp1.DispAll();                                        // expected: (5^2)
    std::cout << (int)pp1.TryMultiple(pp2) << std::endl;  // expected: 1
    pp1.DispAll();                                        // expected: (5^5)
    std::cout << (int)pp1.TryDiv(pp2)      << std::endl;  // expected: 1
    pp1.DispAll();                                        // expected: (5^2)
    pp3.DispAll();                                        // expected: (3^2)
    std::cout << (int)pp1.TryMultiple(pp3) << std::endl;  // expected: 2
    pp1.DispAll();                                        // expected: (5^2)
    std::cout << (int)pp1.TryDiv(pp2)      << std::endl;  // expected: 0
    pp1.DispAll();                                        // expected: (5^2)
    // 注意,实际上应当避免出现下面的情况,执行完后应当立即调用上层类方法删除pp1
    std::cout << (int)pp1.TryDiv(pp1)      << std::endl;  // expected: 2
    pp1.DispAll();                                        // expected: (5^0)
    std::cout << std::endl;
#endif
#if UNIT_TEST >= 4
    std::cout << "unit test4: Factor" << std::endl;
    Factor      factor1(2*2*3*5*7);
    Factor      factor2(3486784401);
    factor1.DispFactor();                             // expected: 420(尚未执行质因数分解)
    factor1.DispCalResult();                          // expected: 420 = 420(尚未执行质因数分解)
    factor2.Factorization();
    factor2.DispCalResult();                          // expected: 3486784401 = (3^20)
    std::cout << (int)factor1.GetLen() << std::endl;  // expected: 255
    factor1.Factorization();
    factor1.DispFactor();                             // expected: (2^2)(3^1)(5^1)(7^1)
    factor1.DispCalResult();                          // expected: 420 == (2^2)(3^1)(5^1)(7^1)
    factor1.TryMultiple(pp2);
    factor1.DispCalResult();                          // expected: 52500 = (2^2)(3^1)(5^4)(7^1)
    factor2.TryMultiple(pp3);                         // expected: TryMultiple(pp)乘法溢出,N=3486784401, pp.toInt=9
    factor2.DispCalResult();                          // expected: 3486784401 = (3^20)
    PrimePow    pp4(5, 2);
    factor1.TryDiv(pp4);
    factor1.DispCalResult();                          // expected: 2100 = (2^2)(3^1)(5^2)(7^1)
    factor1.TryDiv(pp2);                              // expected: TryDiv(pp)除法执行失败,N=2100, pp.toInt=125
    factor1.DispCalResult();                          // expected: 2100 = (2^2)(3^1)(5^2)(7^1)
    factor1.TryDiv(pp4);
    factor1.DispCalResult();                          // expected: 84 = (2^2)(3^1)(7^1)
    factor2.TryMultiple(factor1);                     // expected: TryMultiple(ft)乘法溢出,N=3486784401, ft.m_N=84
    factor2.DispCalResult();                          // expected: 3486784401 = (3^20)
    Factor      factor3(2*3*11);                      
    factor1.TryDiv(factor3);                          // expected: TryDiv(ft)除法溢出,N=84, ft.m_N=66
    factor1.DispCalResult();                          // expected: 84 = (2^2)(3^1)(7^1)
#endif

    // 用于回显终端,输入任意键退出
    getchar();
}
#endif

然后新建一个文件,比如就叫 main.cpp 吧,执行如下代码(注意:要把在 Factor.hpp 代码倒数第三行加入上面的单元测试代码,并将 #define UNIT_TEST 0 改为 #define UNIT_TEST 4)进行单元测试。

// main.cpp
#include "Factor.h"

int main() {
    std::cout << "Hello world!" << std::endl;
    
    UnitTest();

    return 0;
}

输出结果——

Hello world!
unit test1: uint32 MyPow (uint32 base, uint8 pow);
2147483648
3486784401
282475249
5
unit test2: uint32 MyPowMod (uint64 base, uint32 pow, uint32 mod);
262144
1199790
723
33
2147483648
3486784401
282475249
5
unit test3: PrimePow
(5^2)1
(5^5)1
(5^2)(3^2)2
(5^2)0
(5^2)2
(5^0)
unit test4: Factor
420(尚未执行质因数分解)
420 = 420(尚未执行质因数分解)
3486784401 = (3^20)
255
(2^2)(3^1)(5^1)(7^1)
420 = (2^2)(3^1)(5^1)(7^1)
52500 = (2^2)(3^1)(5^4)(7^1)
TryMultiple(pp)乘法溢出,N=3486784401, pp.toInt=9
3486784401 = (3^20)
2100 = (2^2)(3^1)(5^2)(7^1)
TryDiv(pp)除法执行失败,N=2100, pp.toInt=125
2100 = (2^2)(3^1)(5^2)(7^1)
84 = (2^2)(3^1)(7^1)
TryMultiple(ft)乘法溢出,N=3486784401, ft.m_N=84
3486784401 = (3^20)
TryDiv(pp)除法执行失败,N=84, pp.toInt=0
84 = (2^2)(3^1)(7^1)

单元测试正确,收工

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值