两个∑符号,两个∏符号运算公式

本文深入解析了∑(累加)和∏(累乘)符号的运算规则,详细介绍了如何进行两个∑符号或两个∏符号的复合运算,并给出了具体的数学公式和实例计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

两个∑符号,两个∏符号运算

∑符号的意思是累加,∏符号的意思是累乘;
在这里插入图片描述
比如两个这种符号怎么运算呢?

一个 ∑ i = 1 n i \sum_{i=1}^{n} i i=1ni就是一个累加而已,等于 ( n + 1 ) ∗ ( n ) 2 \frac{(n+1)*(n)}{2} 2(n+1)(n),我们可以把 ∑ j = 1 n j \sum_{j=1}^{n} j j=1nj当做常数,提出来,变成了 ∑ j = 1 n j \sum_{j=1}^{n} j j=1nj ∑ i = 1 n i \sum_{i=1}^{n} i i=1ni,等于 ( n + 1 ) 2 ∗ ( n ) 2 4 \frac{(n+1)^2*(n)^2}{4} 4(n+1)2(n)2;

一个 ∏ i = 1 n i \prod_{i=1}^{n} i i=1ni就是一个累乘,等于n! (n的阶乘);它的交换跟求和差不多,先把 ∏ j = 1 n j \prod_{j=1}^{n} j j=1nj提出来,变成 ∏ j = 1 n j \prod_{j=1}^{n} j j=1nj ∏ i = 1 n i \prod_{i=1}^{n} i i=1ni,这里要注意,不是直接等于n!*n!;而是等于 ∏ j = 1 n j ∗ ( n ! ) \prod_{j=1}^{n} j*(n!) j=1nj(n!)等于 ( n ! ) 2 n (n!)^{2n} (n!)2n;

题目:

牛客练习赛52 A题

更新:
解释一下为啥是2n次方

在这里插入图片描述

<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. **处理负数和模运算**:在每一步计中确保数值在模数范围内,避免负数出现。 该代码通过拉格朗日插值法高效计了多项式在给定点的值,适用于大范围的输入参数。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值