【学习笔记】Nim积

定义

定义作用在两个非负整数 a,b 上的运算 ab=mex0i<a,0j<b{(aj)(ib)(ij)},其中 为按位异或操作,也称为 Nim和, 即为 Nim积。

基本性质

与整数的乘法和加法类似,Nim积 和 Nim和 满足交换律,结合律和分配律,即:

  • ab=ba
  • (ab)c=a(bc)
  • (ab)c=acbc

同时,01 分别是 Nim积 的零元和单位元,即:

  • 0a=a0=0
  • 1a=a1=a

由于 Nim积 与整数乘法如此高的相似性,许多由整数乘法和加法实现的算法,均可以用 Nim积 和 Nim和 来代替整数乘法和加法,如高斯消元等。

计算方式

经过数学家们的努力,人们得到了 Nim积 的两条重要规律:

  • k 为满足 22k>a 的非负整数,则 a22k=a22k
  • 22k22k=3222k

其中形如 22k 的数被称为费马数。

有了这两条规律,结合上述的基本性质,我们可以得到一个单次 O(log2n) 复杂度的分治算法:

  • min(a,b)1,返回 ab
  • max(a,b)<28,且曾经计算过 ab,则返回记忆的值。(很强的常数优化)
  • 否则设 k 为满足 22k>max(a,b) 的最小非负整数,a0,b0a,b 较低的 22k1 位,a1,b1a,b 较高的 22k1 位(即 22k1>a0,b0,a1,b1),则:

ab=a0b022k1(a1b0a0b1)(22k122k11)a1b1=a0b022k1((a0a1)(b0b1)a0b0)22k11a1b1

实现代码如下:

ull nimProd(ull x, ull y, int p = 32) {
    if (x <= 1 || y <= 1) return x * y;
    if (p < 8 && rem[x][y]) return rem[x][y];
    ull a = x >> p, b = ((1ull << p) - 1) & x, c = y >> p, d = ((1ull << p) - 1) & y;
    ull bd = nimProd(b, d, p >> 1), ac = nimProd(nimProd(a, c, p >> 1), 1ull << p >> 1, p >> 1), ans;
    ans = ((nimProd(a ^ b, c ^ d, p >> 1) ^ bd) << p) ^ ac ^ bd;
    if (p < 8) rem[x][y] = rem[y][x] = ans;
    return ans;
}

Nim积 的另一个重要性质为:a22k11mod22k

具体证明较为繁琐,珂以类比整数乘法运算中的费马小定理理解。

例题:[SOJ]【WC 联训 Round #6】愤划

posted @   suwakow  阅读(2244)  评论(3编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
Live2D
欢迎阅读『【学习笔记】Nim积』
点击右上角即可分享
微信分享提示