1 条题解

  • 0
    @ 2025-5-7 21:53:03

    解题思路

    1. 输入处理
      读取输入的质数p和字符串s,并将字符串转换为对应的数值数组f。对于字符串中的字符,如果为'*',则对应值为0;否则,字符'a'对应值为1,依此类推。

    2. 拉格朗日插值法
      对于每个字符位置m,计算其对应的基多项式。拉格朗日插值法的核心是通过分母和分子多项式的计算,得到每个基多项式的系数。分母为所有(m - j)的乘积,分子为线性因子的乘积。

    3. 模运算处理
      在质数模p下进行多项式乘法和逆元计算,确保所有运算都在模p下进行。逆元通过费马小定理计算,即a^(p-2) mod p

    4. 系数累加
      将每个基多项式的贡献累加到结果数组a中,最终得到多项式系数。

    5. 结果输出
      输出最终的整数序列,确保所有数值在模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
    上传者