<think>好的,我现在需要解决这个问题:给定一个不超过m-1次的多项式函数f(x),已知数列{a_n}满足a_x = f(x)(x属于正整数)。现在给出这个数列的前m项,要求确定这个数列并求出a_k mod 998244353的值。用户还希望得到C++代码。
首先,我需要理解问题的条件。题目中说f(x)是一个次数不超过m-1次的多项式,因此当已知m个点的时候,这个多项式是唯一确定的。比如,如果m=3,那么多项式是二次的,用三个点就能唯一确定这个多项式。而数列{a_n}的第x项就是f(x)的值。所以给出的前m项应该对应x=1到x=m时的f(x)的值,因为x属于正整数。
接下来,用户需要的是,给定这m个点(也就是前m项的a_1到a_m),求出a_k的值,即f(k)的值,然后对998244353取模。这时候问题转化为如何根据给定的m个点,找到这个多项式,然后代入k计算值。
但直接使用拉格朗日插值法来计算可能效率不高,尤其是当k很大时。比如,k可能是1e18这样的数,这时候直接计算每个基函数然后相乘相加会非常耗时。因此需要寻找一种更高效的方法。
根据拉格朗日插值法的公式,对于给定的点x_1, x_2, ..., x_m(这里题目中的x是自然数,所以x_i = i),那么多项式f(x)可以表示为:
f(x) = sum_{i=1到m} a_i * L_i(x)
其中L_i(x)是拉格朗日基函数。这里的基函数构造是对于点i来说的。例如,当x_i = i的情况下,基函数L_i(x)的形式应该是:
L_i(x) = product_{j=1到m, j≠i} (x - j)/(i - j)
然后代入到f(x)中,得到:
f(x) = sum_{i=1}^m a_i * product_{j≠i} (x-j)/(i-j)
现在的问题是,如何高效计算这个表达式当x=k时的值。
但这里有一个关键点,即给定的多项式的次数不超过m-1次,而我们有m个点,所以这个插值是唯一确定的。因此,我们可以使用拉格朗日插值法直接计算f(k)。不过,当k很大时,比如达到1e9级别,直接计算每一项的乘积可能需要O(m^2)的时间,这在m较大的情况下可能不够高效。例如,当m是1e5时,这样的复杂度可能无法通过时间限制。但题目中并没有给出m的范围,所以可能需要考虑更优的方法,或者题目中的m可能较小?
或者是否存在更高效的算法,例如利用递推或者其他数学方法?
再仔细想,假设x取的是连续的整数,比如x=1,2,…,m。那么拉格朗日插值的公式在这种情况下有没有简化的可能?
在这种情况下,基函数L_i(x)的分母部分可以预先计算。因为分母是product_{j≠i} (i-j)。因为i和j都是从1到m,所以当i固定时,j遍历1到m,但j≠i。因此,分母是(i-1)(i-2)...(1) * (-1)(-2)...(i-m)的乘积。或者说,对于j < i,i-j是正的,j >i时,i-j是负的。或者更准确地说,分母是product_{j=1到m, j≠i} (i - j)。比如,当i=3,m=5,那么分母是(3-1)(3-2)(3-4)(3-5) = 2*1*(-1)*(-2) = 4。这时候,分母的值可能与阶乘有关,或者有某种组合数的形式?
是的,当x_i是连续整数时,分母可以简化为 (i-1)! * (m -i)! * (-1)^(m-i)。比如,对于i来说,当j从1到i-1时,i-j的值是1到i-1,乘积是(i-1)!。对于j从i+1到m时,i-j的值是-1, -2,..., -(m-i),乘积为(-1)^(m-i) * (m-i)!。因此,整个分母为 (i-1)! * (m-i)! * (-1)^{m-i}。这可能是一个简化的方式。
那么,分母的值为:对于i处的分母,可以写成 (i-1)! * (m-i)! * (-1)^{m-i}。这样,每个L_i(x)的分母可以预先计算,这样在计算时,可以节省时间。
那么,当计算f(k)时,可以表示为:
f(k) = sum_{i=1}^m [a_i * product_{j≠i} (k -j)/(i-j) ]
而分母部分可以用上述方式预处理,分子部分则是product_{j=1到m, j≠i} (k-j)。这里的分子可以看作是(k-1)(k-2)...(k-m) / (k-i)。或者,如果总共有m个项相乘,其中不包括j=i的情况,所以分子等于 (k-1)(k-2)...(k-m) / (k-i)。但k可能等于i的情况呢?比如当k是1到m中的某个数,那么此时如果i=k,则分子中的分母项是 (k-i) =0,此时整个表达式是否有问题?但此时,如果k是原始给出的点中的一个,比如k<=m,那么结果就是a_k,不需要计算。所以在这种情况下,当k <=m时,直接返回a_k mod即可。
所以,首先我们需要处理两种情况:当k <=m时,直接返回a_k mod 998244353。否则,需要计算拉格朗日插值的结果。
因此,整个算法的步骤可能是:
1. 如果k <=m,则直接返回a_k mod 998244353。
2. 否则,计算拉格朗日插值多项式在x=k处的值。
现在,考虑如何高效计算这个值。
拉格朗日插值的公式可以变形为:
f(k) = sum_{i=1}^m a_i * [ product_{j=1到m, j≠i} (k-j) / (i-j) ]
分母部分可以预处理,分子部分则是product_{j≠i} (k-j)。
首先,整个分子部分可以表示为 (k-1)(k-2)...(k-m) / (k-i)。因为当j从1到m,排除i的时候,乘积等于总乘积除以(k -i)。比如,总乘积是 (k-1)(k-2)...(k-m),然后除以(k-i),就得到了除了j=i之外的所有项的乘积。
所以,分子部分的乘积是:prod_{j=1}^m (k-j) / (k-i) = [ (k-1)(k-2)...(k-m) ] / (k-i)
而分母部分,根据之前的分析,是 (i-1)! * (m-i)! * (-1)^{m-i}
所以,整个项可以表示为:
a_i * [ (k-1)(k-2)...(k-m) / (k-i) ] / [ (i-1)! (m-i)! (-1)^{m-i} ) ]
简化的话:
a_i * (k-1)(k-2)...(k-m) / [ (k-i) * (i-1)! (m-i)! (-1)^{m-i} ) ]
将符号项和分母合并:
(-1)^{m-i} = (-1)^{m} * (-1)^{-i} }。或者说,(-1)^{m-i} = (-1)^{m} * (-1)^i。或者更简单的方式,可以将分母中的(-1)^{m-i}移到分子,变成 (-1)^{i -m},或者相当于乘以 (-1)^{m-i}的倒数。
但可能这样处理比较复杂。或者,可以重新组织各项:
拉格朗日的基函数L_i(k) = [prod_{j≠i} (k-j)] / [prod_{j≠i} (i-j) ]
其中,分母prod_{j≠i} (i-j) = (i-1)(i-2)...1 * (-1)(-2)...(i-m) )
例如,对于i来说,当j从1到i-1时,i-j是正的,而j从i+1到m时,i-j是负数。总共有m-1项,其中后m-i项都是负数。例如,当j>i时,i-j = -(j-i),所以分母的乘积等于:
(i-1)! * product_{j=i+1}^m (i-j) = (i-1)! * product_{t=1}^{m-i} (-t) ) = (i-1)! * (-1)^{m-i} * (m-i)! )
所以分母为 (i-1)! * (m-i)! ) * (-1)^{m-i} )
所以,分母的倒数就是 1 / [ (i-1)! (m-i)! (-1)^{m-i} ) ]
所以,整个L_i(k) = [ prod_{j≠i} (k-j) ] / [ (i-1)! (m-i)! (-1)^{m-i} ) ]
分子prod_{j≠i} (k-j) = [prod_{j=1}^m (k-j)] / (k-i)
所以,整个式子可以写成:
prod_{j=1}^m (k-j) / (k-i) ) / [ (i-1)! (m-i)! (-1)^{m-i} ) ]
所以,L_i(k) = [ prod_{j=1}^m (k-j) ] / [ (k-i) * (i-1)! (m-i)! (-1)^{m-i} ) ]
然后,f(k) = sum_{i=1}^m a_i * L_i(k )
现在,我们可以将整个表达式拆分为多个部分:
1. 预计算阶乘的逆元,以及阶乘本身,以便快速计算分母中的项。
2. 计算分子中的总乘积,即prod_{j=1}^m (k-j)。如果k大于m,那么当m很大时,这个乘积可能非常大,但我们需要在模下处理。所以我们需要计算这个乘积mod 998244353。
3. 对于每个i,计算分母中的(k-i)的逆元。因为模数是大质数,所以可以用快速幂计算逆元。
4. 对于每个i,计算 (i-1)! 和 (m-i)! 的逆元,以及 (-1)^{m-i} 的影响。
现在,问题转化为如何高效地计算这些部分,并组合起来得到最终的答案。
具体步骤可能如下:
步骤1:预处理阶乘数组fact和逆元数组inv_fact。其中fact[i] = i! mod MOD,inv_fact[i] = (i!)^{-1} mod MOD,其中MOD=998244353。预处理到m的阶乘即可,因为i的范围是1到m,而i-1的最大可能到m-1,所以fact需要处理到m。
步骤2:计算总乘积term = product_{j=1}^m (k-j) mod MOD。这个可以通过循环计算,每次乘以 (k-j) mod MOD。但是当k很大时,比如k是1e9,那么(k-j) mod MOD可以计算为 (k mod MOD - j) mod MOD。这样,不管k有多大,都可以在O(m)的时间内计算这个乘积。
步骤3:对于每个i(从1到m),计算:
分母中的(k-i)的逆元:分母是 (k-i),所以需要计算inv_ki = inverse(k-i) mod MOD。注意,当k ==i时,此时如果k <=m的话已经被处理了,所以这里k>m,所以k-i不可能是0,所以存在逆元。
然后,分子部分是term * inv_ki mod MOD.
分母部分是 (i-1)! * (m-i)! * (-1)^{m-i}。因为模是998244353,所以处理负数的时候要加上MOD。例如,(-1)^{m-i}可以表示为:如果m-i是偶数则为1,否则为MOD-1。
所以,分母的逆元是 inv_denominator = inv_fact[i-1] * inv_fact[m-i] % MOD * pow(-1, m-i) % MOD.
但这里需要注意,pow(-1, m-i)在模运算中的处理。例如,当指数是奇数时,等于MOD-1,否则等于1。所以可以预先计算sign = ( (m-i) %2 ==0 ) ? 1 : MOD-1;
所以,分母的逆元为 inv_denominator = (inv_fact[i-1] * inv_fact[m-i] % MOD ) * sign % MOD.
然后,每个项的贡献是 a_i * (term * inv_ki % MOD) * inv_denominator % MOD.
将所有项的贡献相加,得到总和,最后取模。
综上,整个算法的步骤:
预处理fact和inv_fact数组到m。
如果k <=m,直接返回a[k] % MOD.
否则:
计算term = product_{j=1}^m (k-j) mod MOD.
对每个i from 1 to m:
计算inv_ki = inverse( (k -i) mod MOD )
计算sign = 1 if (m-i) is even else MOD-1.
inv_denominator = inv_fact[i-1] * inv_fact[m-i] % MOD * sign % MOD.
numerator = term * inv_ki % MOD.
contribution = a[i] * numerator % MOD * inv_denominator % MOD.
将所有的contribution相加,得到总和sum,然后sum mod MOD就是答案。
现在,需要处理逆元的计算。因为MOD是质数,所以逆元可以用快速幂计算。比如,inv_ki = pow( (k-i) % MOD, MOD-2, MOD )
但这里的(k-i)可能为负数,所以需要先mod处理。例如,假设k=1e18,i=5,那么k-i mod MOD等于( (k mod MOD ) - i ) mod MOD.
因此,在计算k-i mod MOD的时候,应该写成 ( (k % MOD - i ) % MOD + MOD ) % MOD,以确保结果非负。
这可能在代码中需要注意。
现在,代码的步骤:
预处理fact和inv_fact数组:
fact[0] =1;
for i in 1..m:
fact[i] = fact[i-1] *i % MOD
inv_fact[m] = pow(fact[m], MOD-2, MOD )
for i in m-1 downto 0:
inv_fact[i] = inv_fact[i+1] * (i+1) % MOD
这样,inv_fact[i] = (i! )^{-1} mod MOD.
然后,当k <=m时,直接返回a[k].
否则,计算term:
term =1
for j in 1..m:
term = term * ( (k -j) % MOD ) % MOD
然后,对于每个i:
计算分母中的(k -i) mod MOD,并求逆元:
ki_mod = (k % MOD - i) % MOD
ki_mod = (ki_mod + MOD) % MOD
inv_ki = pow(ki_mod, MOD-2, MOD)
然后,计算sign:
sign = 1 if (m-i) %2 ==0 else MOD-1
计算inv_denominator = inv_fact[i-1] * inv_fact[m-i] % MOD * sign % MOD
然后,计算contribution = a[i] * term % MOD * inv_ki % MOD * inv_denominator % MOD
最后,所有contribution相加,得到sum mod MOD.
这里需要注意的是,数组的索引是否从0开始还是从1开始。比如,输入的a数组可能给出的是前m项,即a_1到a_m。所以在代码中,可能需要将数组存储为从索引1开始。
现在,考虑代码的编写:
假设输入的a数组是从a_1到a_m,存储在一个数组a中,索引是1到m。
预处理fact和inv_fact数组,最大到m。
当k<=m时,输出a[k] mod MOD.
否则:
计算term = product_{j=1}^m (k-j) mod MOD.
然后,对每个i从1到m:
计算ki = (k -i) mod MOD.
inv_ki = pow(ki, MOD-2, MOD).
sign = 1 if (m-i) is even else -1 mod MOD → 即如果(m-i)是偶数,则sign=1,否则sign=MOD-1.
inv_denominator = inv_fact[i-1] * inv_fact[m-i] % MOD → 然后乘以sign mod MOD.
然后分子是term * inv_ki mod MOD.
所以,每个项的贡献是 a[i] * (term * inv_ki % MOD) * (inv_denominator) % MOD.
将所有这些贡献相加,最后模MOD得到结果。
现在,这个方法的复杂度是O(m)预处理阶乘,O(m)计算term,然后O(m)循环处理每个i。总时间复杂度是O(m + m) = O(m),这应该可以处理较大的m,例如m=1e5的情况,但需要看题目给出的时间限制。不过对于编程比赛来说,O(m)的算法是可行的。
现在,编写代码的时候需要注意以下几点:
1. 如何处理负数的模运算,比如k-i可能为负数,所以在计算ki_mod时,需要加上MOD后再取模。
例如,ki_mod = (k % MOD - i) % MOD → 这可能导致负数,所以应该写成:
ki_mod = ( (k % MOD - i) % MOD + MOD ) % MOD;
或者更简洁的方式:
ki_mod = (k - i) % MOD;
因为当k很大时,k -i可能很大,但模运算自动处理为余数。例如,在C++中,负数的取模可能得到负数,所以需要调整为正数。
在C++中,可以使用以下方法:
long long ki = (k - i) % MOD;
if (ki < 0) ki += MOD;
然后,ki_mod = ki % MOD;
或者,更简单的方式:
long long ki_mod = ( (k % MOD - i) % MOD + MOD ) % MOD;
这样可以确保结果非负。
2. 预处理阶乘和逆元阶乘数组时,数组的大小需要足够大。例如,当m最大可能为1e5时,数组需要开到1e5+1的大小。
现在,编写C++代码:
假设输入为m,k,然后输入m个整数,表示a_1到a_m。
代码的大体结构如下:
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
int main() {
int m;
long long k;
cin >> m >> k;
vector<long long> a(m + 1); // a[1] ~ a[m]
for (int i = 1; i <= m; ++i) {
cin >> a[i];
}
if (k <= m) {
cout << a[k] % MOD << endl;
return 0;
}
// Precompute fact and inv_fact
vector<long long> fact(m + 1), inv_fact(m + 1);
fact[0] = 1;
for (int i = 1; i <= m; ++i) {
fact[i] = fact[i - 1] * i % MOD;
}
inv_fact[m] = 1;
// Compute inv_fact[m] using Fermat's little theorem
long long inv = 1, base = fact[m];
int exp = MOD - 2;
while (exp) {
if (exp % 2) inv = inv * base % MOD;
base = base * base % MOD;
exp /= 2;
}
inv_fact[m] = inv;
for (int i = m - 1; i >= 0; --i) {
inv_fact[i] = inv_fact[i + 1] * (i + 1) % MOD;
}
// Compute term = product_{j=1}^m (k - j) mod MOD
long long term = 1;
for (int j = 1; j <= m; ++j) {
long long val = (k - j) % MOD;
if (val < 0) val += MOD;
term = term * val % MOD;
}
long long sum = 0;
for (int i = 1; i <= m; ++i) {
// Compute inv_ki: inverse of (k - i) mod MOD
long long ki_mod = (k - i) % MOD;
if (ki_mod < 0) ki_mod += MOD;
if (ki_mod == 0) {
// This should not happen since k > m >= i
}
long long inv_ki = 1;
// Compute inv_ki using Fermat's
inv_ki = pow(ki_mod, MOD - 2); // 需要实现快速幂函数
// 或者,使用快速幂代码:
long long exp = MOD - 2;
inv_ki = 1;
long long base = ki_mod;
while (exp) {
if (exp & 1) inv_ki = inv_ki * base % MOD;
base = base * base % MOD;
exp >>= 1;
}
// Compute sign: (-1)^(m -i)
int sign = ((m - i) % 2 == 0) ? 1 : MOD - 1;
// Compute inv_denominator: inv_fact[i-1] * inv_fact[m -i] * sign mod MOD
long long inv_denominator = inv_fact[i - 1] * inv_fact[m - i] % MOD;
inv_denominator = inv_denominator * sign % MOD;
// Contribution: a[i] * term * inv_ki % MOD * inv_denominator % MOD
long long contrib = a[i] % MOD;
contrib = contrib * term % MOD;
contrib = contrib * inv_ki % MOD;
contrib = contrib * inv_denominator % MOD;
sum = (sum + contrib) % MOD;
}
cout << (sum % MOD + MOD) % MOD << endl;
return 0;
}
但这里需要注意的是,pow函数的实现需要自己写,或者用循环快速幂。
此外,在代码中,当计算inv_fact[m]时,可以通过费马小定理计算逆元。这里已经用快速幂的方式处理。
另外,需要注意变量类型,尤其是当k很大时,比如k是long long类型,所以在计算(k -j)的时候,要用long long类型。
此外,当m=0时如何处理?但题目中m应该至少为1,因为多项式次数是m-1次,所以m≥1。
另外,在测试中,例如:
样例输入:
m=3, k=4, a_1=1, a_2=4, a_3=9。即多项式f(x)是平方函数,次数2次,不超过3-1=2次。这时,当k=4时,a_4应该等于16。计算:
term = (4-1)*(4-2)*(4-3) = 3*2*1=6 mod MOD=6.
然后,对每个i=1,2,3:
i=1:
ki_mod=4-1=3 mod MOD=3 → inv_ki=3^(MOD-2) mod MOD=332748118.
sign = (3-1)的奇偶性?m=3, i=1 → m-i=2 → 偶 → sign=1.
inv_denominator = inv_fact[0] * inv_fact[3-1=2] * 1 mod MOD.
inv_fact[0]=1(因为0!的逆元是1),inv_fact[2] = (2! )^{-1} mod MOD=499122177.
所以 inv_denominator=1 * 499122177 * 1 mod MOD=499122177.
贡献:a_1=1 * term=6 * inv_ki=332748118 * inv_denominator=499122177 mod MOD.
计算:
1 *6=6 → 6 *332748118 mod MOD → 6*332748118=1996488708 → mod MOD:1996488708 / 998244353=2*998244353=1996488706 →余2 → 1996488708 mod MOD=2.
2 *499122177 mod MOD= 998244354 mod MOD=1.
所以i=1的贡献是1.
i=2:
ki_mod=4-2=2 mod MOD=2 → inv_ki=499122177.
sign=3-2=1 → 奇 → sign=MOD-1=998244352.
inv_denominator=inv_fact[1] * inv_fact[3-2=1] * 998244352 mod MOD.
inv_fact[1]=1!^{-1}=1.
inv_fact[1] again=1. 所以乘积是1*1=1 ×998244352 → 998244352.
贡献:a_2=4 → 4*6=24 → 24*inv_ki=24*499122177 mod MOD → 24*499122177=11978932248 → mod 998244353:
计算998244353 *12=11978932236 → 11978932248 -11978932236=12 → mod后是12.
然后乘以 inv_denominator=998244352 → 12 *998244352 = 11978932224 → mod MOD:
11978932224 mod 998244353 = 11978932224 - 12*998244353=11978932224 - 11978932236= -12 → +MOD → 998244341.
所以贡献是4*6*499122177%MOD *998244352%MOD → 但可能计算步骤需要更细致。
或者,更简单的方式:
每个步骤计算:
contrib = a[i] * term % MOD → 4*6=24 → 24 mod MOD=24.
乘以 inv_ki=499122177 → 24 *499122177=11978932248 → mod MOD=11978932248 mod MOD=12.
然后乘以 inv_denominator=998244352 →12 *998244352=11978932224 → mod MOD=11978932224 - 12*998244353= -12 → 998244353-12=998244341.
所以i=2的贡献是998244341.
i=3:
ki_mod=4-3=1 → inv_ki=1.
sign=m-i=0 → 0是偶 → sign=1.
inv_denominator=inv_fact[3-1=2] * inv_fact[0] → inv_fact[2]=499122177, inv_fact[0]=1.
所以 inv_denominator=499122177 *1 *1=499122177.
贡献:a_3=9 →9*6=54 →54 *1=54 →54 *499122177 mod MOD.
54 *499122177=54 *499,122,177 = ?
计算54*499,122,177 mod 998244353:
54 ×499,122,177 = 54 × (500,000,000 - 877,823) = 54×500,000,000 -54×877,823 → 27,000,000,000 -47,402,442 = 26,952,597,558.
mod MOD:
998244353 ×27 = 26,952,597,531 → 26,952,597,558 -26,952,597,531 =27 → 27 mod MOD=27.
所以贡献是27.
总和sum=1 +998244341 +27 → (1+998244341)=998244342 mod MOD. 998244342 +27=998244369 mod MOD → 998244369-998244353=16 → 16 mod MOD=16.
而正确的结果是a_4=16,所以计算正确。
因此,代码是正确的。</think>以下是解决该问题的C++代码实现:
```cpp
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
long long mod_pow(long long base, long long exp) {
long long result = 1;
base %= MOD;
while (exp > 0) {
if (exp % 2 == 1)
result = (result * base) % MOD;
base = (base * base) % MOD;
exp /= 2;
}
return result;
}
int main() {
int m;
long long k;
cin >> m >> k;
vector<long long> a(m + 1);
for (int i = 1; i <= m; ++i) {
cin >> a[i];
}
if (k <= m) {
cout << a[k] % MOD << endl;
return 0;
}
// 预处理阶乘和逆元阶乘
vector<long long> fact(m + 1), inv_fact(m + 1);
fact[0] = 1;
for (int i = 1; i <= m; ++i) {
fact[i] = fact[i - 1] * i % MOD;
}
inv_fact[m] = mod_pow(fact[m], MOD - 2);
for (int i = m - 1; i >= 0; --i) {
inv_fact[i] = inv_fact[i + 1] * (i + 1) % MOD;
}
// 计算分子总乘积 term = product(k-j) mod MOD
long long term = 1;
for (int j = 1; j <= m; ++j) {
long long val = (k - j) % MOD;
if (val < 0) val += MOD;
term = term * val % MOD;
}
long long sum = 0;
for (int i = 1; i <= m; ++i) {
// 计算 (k-i) 的逆元
long long ki_mod = (k - i) % MOD;
if (ki_mod < 0) ki_mod += MOD;
long long inv_ki = mod_pow(ki_mod, MOD - 2);
// 计算符号 (-1)^(m-i)
int sign = ((m - i) % 2 == 0) ? 1 : MOD - 1;
// 计算分母的逆元
long long inv_denominator = inv_fact[i - 1] * inv_fact[m - i] % MOD;
inv_denominator = inv_denominator * sign % MOD;
// 计算当前项的贡献
long long contrib = a[i] % MOD;
contrib = contrib * term % MOD;
contrib = contrib * inv_ki % MOD;
contrib = contrib * inv_denominator % MOD;
sum = (sum + contrib) % MOD;
}
cout << (sum % MOD + MOD) % MOD << endl;
return 0;
}
```
### 代码说明:
1. **预处理阶乘和逆元**:为了高效计算组合数,预处理阶乘数组 `fact` 和逆元阶乘数组 `inv_fact`。
2. **处理特殊情况**:当 `k ≤ m` 时,直接输出 `a[k]`,因为多项式在已知点处值已知。
3. **计算总乘积项**:计算拉格朗日插值公式中的公共乘积项 `term = ∏(k-j)`。
4. **逐项计算贡献**:对每个已知点计算其在插值多项式中的贡献,利用预处理好的阶乘和逆元加速计算。
5. **处理负数和模运算**:在每一步计算中确保数值在模数范围内,避免负数出现。
该代码通过拉格朗日插值法高效计算了多项式在给定点的值,适用于大范围的输入参数。