LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
berlekamp.cpp
浏览该文件的文档.
2
3namespace LMCAS {
4using namespace berlekamp_detail;
5
6/**
7 * @brief 将模 p 系数向量转换为 Polynomial<ModInt>.
8 *
9 * @param[in] coeffs 系数向量(升幂排列)
10 * @param[in] p 素数模数
11 * @param[in] var 变量名
12 * @return 对应的 Polynomial<ModInt>
13 * @internal
14 */
16 const std::vector<int64_t>& coeffs,
17 int64_t p,
18 const std::string& var) {
19
20 std::vector<ModInt> mod_coeffs;
21 mod_coeffs.reserve(coeffs.size());
22 for (int64_t c : coeffs) {
23 mod_coeffs.emplace_back(c, p);
24 }
25 /// 直接构造,不调用 trim()(已保证无高次零系数)
26 Polynomial<ModInt> result(var);
27 result.coeffs = std::move(mod_coeffs);
28 return result;
29}
30
32 const Polynomial<Rational>& poly,
33 int64_t prime) {
34
35 BerlekampResult result;
36
37 /// 零多项式或常数多项式:无因子
38 if (poly.is_zero() || poly.degree() <= 0) {
39 return result;
40 }
41
42 /// 显式和自动模数都必须保持次数且使约化多项式无平方。
43 int64_t p = prime;
44 if (p > 0) {
45 if (!bk_is_suitable_prime(poly, p)) {
46 return result;
47 }
48 } else {
49 p = bk_select_prime(poly);
50 if (p < 0) {
51 return result;
52 }
53 }
54
55 result.prime = p;
56
57 /// 将多项式约化到 F_p
58 std::vector<int64_t> f_coeffs = bk_reduce_to_mod_coeffs(poly, p);
59
60 /// 首一化
61 if (!f_coeffs.empty()) {
62 int64_t lc = f_coeffs.back();
63 if (lc != 1) {
64 int64_t lc_inv = bk_mod_inverse(lc, p);
65 for (auto& c : f_coeffs) {
66 c = (c * lc_inv) % p;
67 }
68 }
69 }
70
71 /// 线性多项式:本身不可约
72 if (f_coeffs.size() <= 2) {
73 result.factors.push_back(bk_to_poly_modint(f_coeffs, p, poly.variable_name));
74 return result;
75 }
76
77 /// 构造 Berlekamp 矩阵 Q
78 auto Q = bk_build_q_matrix(f_coeffs, p);
79
80 /// 计算 (Q - I)^T 的零空间
81 auto null_basis = bk_null_space(Q, p);
82 int null_dim = static_cast<int>(null_basis.size());
83
84 /// 存储零空间信息
85 result.null_space_dim = null_dim;
86 result.null_space_basis = null_basis;
87
88 /// 零空间维度 = 1:多项式在 F_p 上不可约
89 if (null_dim <= 1) {
90 result.factors.push_back(bk_to_poly_modint(f_coeffs, p, poly.variable_name));
91 return result;
92 }
93
94 /// 零空间维度 > 1:多项式可分解,使用基向量分裂
95 auto split = bk_split_factors(f_coeffs, null_basis, null_dim, p);
96 for (const auto& factor_coeffs : split) {
97 result.factors.push_back(bk_to_poly_modint(factor_coeffs, p, poly.variable_name));
98 }
99 return result;
100}
101
102}
一元多项式模板类
std::string variable_name
变量名
bool is_zero() const
判断是否为零多项式
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
int degree() const
获取多项式的次数
int64_t bk_mod_inverse(int64_t a, int64_t p)
模 p 下求乘法逆元.
std::vector< std::vector< int64_t > > bk_build_q_matrix(const std::vector< int64_t > &f, int64_t p)
构造 F_p 上的 Berlekamp 矩阵 Q。
bool bk_is_suitable_prime(const Polynomial< Rational > &poly, int64_t prime)
判断素数是否保持多项式次数和无平方性质。
std::vector< std::vector< int64_t > > bk_null_space(const std::vector< std::vector< int64_t > > &Q, int64_t p)
std::vector< std::vector< int64_t > > bk_split_factors(const std::vector< int64_t > &f_coeffs, const std::vector< std::vector< int64_t > > &null_basis, int null_dim, int64_t p)
std::vector< int64_t > bk_reduce_to_mod_coeffs(const Polynomial< Rational > &poly, int64_t p)
以系数分母的 LCM 清除分母,再逐项取模 p。
int64_t bk_select_prime(const Polynomial< Rational > &poly)
从小素数表中选取适合 Berlekamp 分解的素数。
const VectorField const VectorField & c
BerlekampResult berlekamp_factor(const Polynomial< Rational > &poly, int64_t prime)
static Polynomial< ModInt > bk_to_poly_modint(const std::vector< int64_t > &coeffs, int64_t p, const std::string &var)
将模 p 系数向量转换为 Polynomial<ModInt>.
Berlekamp 分解结果。
int null_space_dim
零空间维度,等于不可约因子数。
std::vector< std::vector< int64_t > > null_space_basis
零空间基向量。
std::vector< Polynomial< ModInt > > factors
模 p 下的不可约因子。
int64_t prime
使用的素数。