云计算百科
云计算领域专业知识百科平台

【C++竞赛】取模

取模运算的意义

取模运算(Modulo Operation)在计算机科学和数学中具有广泛的应用。其核心作用是将数值限制在特定范围内,避免溢出或简化问题。

取模运算通常表示为 a % m,结果为 a 除以 m 的余数。数学上定义为:
[amod  m=a−m⋅⌊am⌋][ a \\mod m = a – m \\cdot \\left\\lfloor \\frac{a}{m} \\right\\rfloor ][amodm=amma]

取模运算的主要意义包括:

  • 防止数值溢出:在计算机中,数值类型有范围限制,取模可将大数映射到有限范围内。
  • 循环性质:取模运算具有周期性,适合处理循环结构(如时间、角度)。
  • 密码学应用:在加密算法中广泛使用模运算来保证安全性。
  • 算法优化:在动态规划、数论问题中,取模可简化计算。

标准模数 998244353

在算法竞赛和数学问题中,998244353 是一个常用的标准模数,其选择基于以下特性:

  • 质数性质:

    • 998244353 是一个大质数((223×119+1)(2^{23} \\times 119 + 1)(223×119+1)),其值为 (998244353)(998244353)(998244353)
    • 质数的性质保证了模运算下的除法(乘法逆元)存在且唯一。
  • 原根存在性:

    • 该模数的最小原根为 3,适合快速数论变换(NTT),用于高效计算多项式乘法。
  • 数值范围:

    • 介于 (108)到(109)(10^8) 到 (10^9)(108)(109)之间,适合 32 位整数运算,避免溢出。
    • 平方不超过 64 位整数范围((9982443532<263))((998244353^2 < 2^{63}))(9982443532<263)
  • 计算效率:

    • 二进制表示为 11101110000000000001110000000001,便于位运算优化。
    • 模数减一((998244352))的质因数分解为 (223×119)(2^{23} \\times 119)(223×119),适合分治算法。
  • 取模运算的实现

    在编程中,取模运算需注意负数处理。例如在 C++ 中:

    const int MOD = 998244353;
    int mod(int a) {
    return (a % MOD + MOD) % MOD;
    }

    对于乘法取模,需防止中间结果溢出:

    int mul_mod(int a, int b) {
    return (1LL * a * b) % MOD;
    }

    逆元计算

    在模运算中,除法通过乘法逆元实现。根据费马小定理,若 MOD 为质数,则逆元为:
    [a−1≡aMOD−2(modMOD)][ a^{-1} \\equiv a^{MOD-2} \\pmod{MOD} ][a1aMOD2(modMOD)]
    代码实现:

    int inv(int a) {
    int res = 1, p = MOD 2;
    while (p) {
    if (p & 1) res = mul_mod(res, a);
    a = mul_mod(a, a);
    p >>= 1;
    }
    return res;
    }

    实际应用

    在动态规划或组合数学问题中,常需预计算阶乘和逆阶乘:

    vector<int> fact(MAXN, 1), inv_fact(MAXN, 1);
    void init() {
    for (int i = 1; i < MAXN; i++) {
    fact[i] = mul_mod(fact[i1], i);
    inv_fact[i] = inv(fact[i]);
    }
    }

    这种设计确保了模运算的高效性和正确性,同时避免了数值溢出问题。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【C++竞赛】取模
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!