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

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

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

复数域

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

模素数域(素数自选)

如果有素数 p 和正整数 m 满足 m|(p1),则可以在 Fp 下找到 m 次本原单位根(即原根的 (p1)/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 极小,则可以扩域维护每个数为 f0+f1w+f2w2++fm1wm1 的形式,最后将这个多项式模 m 级分圆多项式 Φm(w) 获得真实值。

分圆多项式

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

Φn(x)=(xw1)(xw2)(xwφ(n))=i=0n1(xwi)[gcd(i,n)=1]

其中 w1,w2,,wφ(n) 是全部 n 次本原单位根,ww1,w2,,wφ(n) 中任取。根据一些资料可以得知:

d|nΦd(x)=xn1

Φn(x)=(1)[n=1]d|n(1xd)μ(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 @   caijianhong  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示