如何在复数域或模素数域下找单位根

如何在复数域或模素数域下找单位根

参考文章:CF1103E Radix sum - 洛谷专栏数学小记 #3:从 CF1103E 浅谈异或卷积 - 洛谷专栏

复数域

可以使用 polar(1, 2 * pi / m) 获得复数域下的 \(m\) 次本原单位根。需要慎重使用这样的单位根。

模素数域(素数自选)

如果有素数 \(p\) 和正整数 \(m\) 满足 \(m|(p-1)\),则可以在 \(\mathbb F_p\) 下找到 \(m\) 次本原单位根(即原根的 \((p-1)/m\) 次方)。

洛谷原根模板题太恶臭了,在这里放一下求原根的代码:

// mint 是 F_p 下的数,代码求出 p 的最小原根
mint pmroot() {
  vector<int> pri;
  int m = mint::mod - 1;
  for (int i = 2; i * i <= m; i++) if (m % i == 0) {
    pri.push_back(i);
    while (m % i == 0) m /= i;
  }
  if (m > 1) pri.push_back(m);
  m = mint::mod - 1;
  for (mint g = 1; ; g += 1) {
    bool flag = false;
    for (int p : pri) {
      if (qpow(g, m / p) == 1) flag = true;
    }
    if (!flag) return g;
  }
  throw -1;
}

模素数域

\(m\) 极小,则可以扩域维护每个数为 \(f_0+f_1w+f_2w^2+\cdots+f_{m-1}w^{m-1}\) 的形式,最后将这个多项式模 \(m\) 级分圆多项式 \(\Phi_m(w)\) 获得真实值。

分圆多项式

\(m\) 级分圆多项式 \(\Phi_m(x)\) 是一个在 \(\mathbb Z[x]\)\(\varphi(m)\) 次的不可约首一多项式,满足

\[\Phi_n(x)=(x-w_1)(x-w_2)\cdots(x-w_{\varphi(n)})=\prod_{i=0}^{n-1}(x-w^i)^{[\gcd(i, n)=1]} \]

其中 \(w_1, w_2, \cdots, w_{\varphi(n)}\) 是全部 \(n\) 次本原单位根,\(w\)\(w_1, w_2, \cdots, w_{\varphi(n)}\) 中任取。根据一些资料可以得知:

\[\prod_{d|n}\Phi_d(x)=x^n-1 \]

\[\Phi_n(x)=(-1)^{[n=1]}\prod_{d|n}(1-x^d)^{\mu(n/d)} \]

void init() {  // k 次分圆多项式,次数为 phi[k]
  T[0] = 1;
  for (auto i : d[k]) {  // d[k] 是 k 的所有因子
    if (mu[k / i] == 1)
      for (int j = phi[k]; j >= i; j--) T[j] -= T[j - i];
    else if (mu[k / i] == -1)
      for (int j = i; j <= phi[k]; j++) T[j] += T[j - i];  // 实际上是退背包
  }
}
posted @ 2025-02-26 08:24  caijianhong  阅读(59)  评论(0)    收藏  举报