取模运算优化超级算法

举报
兔老大 发表于 2022/09/25 01:51:25 2022/09/25
【摘要】 #ifndef LOCAL#define NDEBUG#endif#include <algorithm>#include <cassert>#include <cstring>#include <functional>#include <initializer_list>#i...

  
  1. #ifndef LOCAL
  2. #define NDEBUG
  3. #endif
  4. #include <algorithm>
  5. #include <cassert>
  6. #include <cstring>
  7. #include <functional>
  8. #include <initializer_list>
  9. #include <iostream>
  10. #include <memory>
  11. #include <queue>
  12. #include <random>
  13. #include <vector>
  14. template <std::uint32_t P> struct ModInt32 {
  15. public:
  16. using i32 = std::int32_t;
  17. using u32 = std::uint32_t;
  18. using i64 = std::int64_t;
  19. using u64 = std::uint64_t;
  20. using m32 = ModInt32;
  21. private:
  22. u32 v;
  23. static constexpr u32 get_r() {
  24. u32 iv = P;
  25. for (u32 i = 0; i != 4; ++i) iv *= 2U - P * iv;
  26. return -iv;
  27. }
  28. static constexpr u32 r = get_r(), r2 = -u64(P) % P;
  29. static_assert((P & 1) == 1);
  30. static_assert(-r * P == 1);
  31. static_assert(P < (1 << 30));
  32. static constexpr u32 pow_mod(u32 x, u64 y) {
  33. u32 res = 1;
  34. for (; y != 0; y >>= 1, x = u64(x) * x % P)
  35. if (y & 1) res = u64(res) * x % P;
  36. return res;
  37. }
  38. static constexpr u32 reduce(u64 x) { return x + u64(u32(x) * r) * P >> 32; }
  39. static constexpr u32 norm(u32 x) { return x - (P & -(x >= P)); }
  40. public:
  41. static constexpr u32 get_pr() {
  42. u32 tmp[32] = {}, cnt = 0;
  43. const u64 phi = P - 1;
  44. u64 m = phi;
  45. for (u64 i = 2; i * i <= m; ++i)
  46. if (m % i == 0) {
  47. tmp[cnt++] = i;
  48. while (m % i == 0) m /= i;
  49. }
  50. if (m != 1) tmp[cnt++] = m;
  51. for (u64 res = 2; res != P; ++res) {
  52. bool flag = true;
  53. for (u32 i = 0; i != cnt && flag; ++i) flag &= pow_mod(res, phi / tmp[i]) != 1;
  54. if (flag) return res;
  55. }
  56. return 0;
  57. }
  58. ModInt32() = default;
  59. ~ModInt32() = default;
  60. constexpr ModInt32(u32 v) : v(reduce(u64(v) * r2)) {}
  61. constexpr ModInt32(const m32 &rhs) : v(rhs.v) {}
  62. constexpr u32 get() const { return norm(reduce(v)); }
  63. explicit constexpr operator u32() const { return get(); }
  64. explicit constexpr operator i32() const { return i32(get()); }
  65. constexpr m32 &operator=(const m32 &rhs) { return v = rhs.v, *this; }
  66. constexpr m32 operator-() const {
  67. m32 res;
  68. return res.v = (P << 1 & -(v != 0)) - v, res;
  69. }
  70. constexpr m32 inv() const { return pow(-1); }
  71. constexpr m32 &operator+=(const m32 &rhs) {
  72. return v += rhs.v - (P << 1), v += P << 1 & -(v >> 31), *this;
  73. }
  74. constexpr m32 &operator-=(const m32 &rhs) { return v -= rhs.v, v += P << 1 & -(v >> 31), *this; }
  75. constexpr m32 &operator*=(const m32 &rhs) { return v = reduce(u64(v) * rhs.v), *this; }
  76. constexpr m32 &operator/=(const m32 &rhs) { return this->operator*=(rhs.inv()); }
  77. friend m32 operator+(const m32 &lhs, const m32 &rhs) { return m32(lhs) += rhs; }
  78. friend m32 operator-(const m32 &lhs, const m32 &rhs) { return m32(lhs) -= rhs; }
  79. friend m32 operator*(const m32 &lhs, const m32 &rhs) { return m32(lhs) *= rhs; }
  80. friend m32 operator/(const m32 &lhs, const m32 &rhs) { return m32(lhs) /= rhs; }
  81. friend bool operator==(const m32 &lhs, const m32 &rhs) { return norm(lhs.v) == norm(rhs.v); }
  82. friend bool operator!=(const m32 &lhs, const m32 &rhs) { return norm(lhs.v) != norm(rhs.v); }
  83. friend std::istream &operator>>(std::istream &is, m32 &rhs) {
  84. return is >> rhs.v, rhs.v = reduce(u64(rhs.v) * r2), is;
  85. }
  86. friend std::ostream &operator<<(std::ostream &os, const m32 &rhs) { return os << rhs.get(); }
  87. constexpr m32 pow(i64 y) const {
  88. if ((y %= P - 1) < 0) y += P - 1; // phi(P) = P - 1, assume P is a prime number
  89. m32 res(1), x(*this);
  90. for (; y != 0; y >>= 1, x *= x)
  91. if (y & 1) res *= x;
  92. return res;
  93. }
  94. };
  95. int main() {
  96. #ifdef LOCAL
  97. std::freopen("..\\in", "r", stdin), std::freopen("..\\out", "w", stdout);
  98. #endif
  99. std::ios::sync_with_stdio(false);
  100. std::cin.tie(0);
  101. // 使用方法: ModInt32<7> a(3);
  102. ModInt32<7> a(11);
  103. std::cout << a;
  104. return 0;
  105. }

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/126829172

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。