1 条题解
-
0
解题思路
-
输入处理
读取输入的质数p
和字符串s
,并将字符串转换为对应的数值数组f
。对于字符串中的字符,如果为'*'
,则对应值为0
;否则,字符'a'
对应值为1
,依此类推。 -
拉格朗日插值法
对于每个字符位置m
,计算其对应的基多项式。拉格朗日插值法的核心是通过分母和分子多项式的计算,得到每个基多项式的系数。分母为所有(m - j)
的乘积,分子为线性因子的乘积。 -
模运算处理
在质数模p
下进行多项式乘法和逆元计算,确保所有运算都在模p
下进行。逆元通过费马小定理计算,即a^(p-2) mod p
。 -
系数累加
将每个基多项式的贡献累加到结果数组a
中,最终得到多项式系数。 -
结果输出
输出最终的整数序列,确保所有数值在模p
下正确。
代码实现
#include <iostream> #include <vector> #include <string> using namespace std; // 计算模幂,处理大数幂运算的模运算 int mod_pow(int base, int exp, int mod) { int result = 1; base %= mod; while (exp > 0) { if (exp % 2 == 1) { result = (result * (long long)base) % mod; } base = (base * (long long)base) % mod; exp /= 2; } return result; } int main() { int N; cin >> N; // 读取测试用例数量 while (N--) { int p; // 质数p string s; // 输入字符串 cin >> p >> s; int n = s.size(); // 字符串长度 vector<int> f(n); // 将字符串转换为数值数组 for (int i = 0; i < n; ++i) { if (s[i] == '*') { f[i] = 0; // 特殊字符'*'对应值为0 } else { f[i] = s[i] - 'a' + 1; // 字符'a'对应值为1,依此类推 } } vector<int> a(n); // 初始化结果数组 for (int i = 0; i < n; ++i) { a[i] = 0; } for (int m = 1; m <= n; ++m) { // 计算拉格朗日插值法中的分母 int denominator = 1; for (int j = 1; j <= n; ++j) { if (j == m) continue; // 跳过m自身 denominator = (denominator * (long long)(m - j)) % p; } denominator = (denominator + p) % p; // 确保分母为正 int inv_denominator = mod_pow(denominator, p - 2, p); // 计算分母的逆元 // 展开分子多项式 vector<int> current_coeff(1, 1); // 初始多项式系数为1 for (int j = 1; j <= n; ++j) { if (j == m) continue; // 跳过m自身 vector<int> new_coeff(current_coeff.size() + 1, 0); // 新的多项式系数 for (int k = 0; k < current_coeff.size(); ++k) { new_coeff[k] = (new_coeff[k] + ((-j) * (long long)current_coeff[k]) % p) % p; new_coeff[k] = (new_coeff[k] + p) % p; // 确保系数为正 new_coeff[k + 1] = (new_coeff[k + 1] + current_coeff[k]) % p; new_coeff[k + 1] = (new_coeff[k + 1] + p) % p; // 确保系数为正 } current_coeff.swap(new_coeff); // 更新多项式系数 } int f_val = f[m - 1]; // 当前位置的函数值 // 将基多项式的贡献累加到结果数组 for (int i = 0; i < n; ++i) { int term = (current_coeff[i] * (long long)inv_denominator) % p; term = (term * (long long)f_val) % p; a[i] = (a[i] + term) % p; } } // 确保结果数组中的所有数值在模p下正确 for (int i = 0; i < n; ++i) { a[i] = (a[i] % p + p) % p; } // 输出最终的整数序列 for (int i = 0; i < n; ++i) { if (i > 0) cout << " "; cout << a[i]; } cout << '\n'; } return 0; }
注释说明
mod_pow
函数:用于计算模幂,处理大数幂运算的模运算。通过快速幂算法实现。- 输入处理:读取输入的测试用例数量
N
,并逐个处理每个测试用例。将字符串s
转换为数值数组f
。 - 分母计算:计算拉格朗日插值法中的分母,并处理模运算。分母为所有
(m - j)
的乘积,确保分母为正。 - 分子多项式展开:通过逐步相乘线性因子,展开分子多项式,并处理模运算。每次乘以一个线性因子时,更新多项式系数。
- 逆元和系数累加:计算分母的逆元,并将基多项式的贡献累加到结果数组
a
中。 - 结果输出:输出最终的整数序列,确保所有数值在模
p
下正确。
-
- 1
信息
- ID
- 1066
- 时间
- 1000ms
- 内存
- 30MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者