题目大意:求 ∑i=1nik\displaystyle\sum_{i = 1}^ni^ki=1∑n​ik
求k次幂有多种求法,例如:
伯努利数求k次幂之和(待补)
斯特林数求k次幂之和
拉格朗日插值法求k次幂之和

这里采用拉格朗日插值法进行求解。
拉格朗日可以通过 k+1k + 1k+1 个点唯一确定一个 kkk 次多项式,它的公式为:f(x)=∑i=1ny[i]∏i≠jx−x[j]x[i]−x[j]f(x) = \sum_{i = 1}^ny[i] \prod_{i \neq j}\frac{x - x[j]}{x[i]-x[j]}f(x)=i=1∑n​y[i]i​=j∏​x[i]−x[j]x−x[j]​
其中x[i],y[i]x[i],y[i]x[i],y[i]对应已知的点值,对已知的点很容易通过代入验证正确性,带入 x[i]x[i]x[i] 将会得到 y[i]y[i]y[i]

这个式子在一般情况下的复杂度为 O(n2)O(n^2)O(n2),比高斯消元的 n3n^3n3 更加优秀,在已知点的 xxx 取值连续的情况下,复杂度能降低到 O(n)O(n)O(n),只要预处理阶乘逆元,以及 xxx 的 k + 1 项倒阶乘:xfacxfacxfac。
f(x)=∑i=1ny[i]∗xfacfac[i]∗fac[n−i]∗(x−i)f(x)=\sum_{i = 1}^ny[i]*\frac{xfac}{fac[i]*fac[n - i]*(x-i)}f(x)=i=1∑n​y[i]∗fac[i]∗fac[n−i]∗(x−i)xfac​

为什么这题可以用拉格朗日插值
当然是因为 ∑i=1nik\displaystyle\sum_{i = 1}^ni^ki=1∑n​ik 是一个以n为自变量的多项式,并且是 k+1k + 1k+1 次多项式
证明:
令S(n,k)=∑i=1nik\displaystyle S(n,k)=\sum_{i = 1}^ni^kS(n,k)=i=1∑n​ik
对这个序列两两差分可以得到:(n+1)k+1−nk+1=∑i=0k+1C(k+1,i)∗ni−nk+1=∑i=0kC(k+1,i)∗ni(n + 1)^{k+1} - n^{k+1}=\sum_{i = 0}^{k+1}C(k+1,i)*n^i - n^{k+1}=\sum_{i = 0}^kC(k+1,i)*n^i(n+1)k+1−nk+1=i=0∑k+1​C(k+1,i)∗ni−nk+1=i=0∑k​C(k+1,i)∗nink+1−(n−1)k+1=∑i=0kC(k+1,i)∗(n−1)in^{k+1} - (n-1)^{k+1}=\sum_{i = 0}^{k}C(k+1,i)*(n-1)^ink+1−(n−1)k+1=i=0∑k​C(k+1,i)∗(n−1)i.........1k+1−0k+1=∑i=0kC(k+1,i)0i1^{k+1}-0^{k+1}=\sum_{i = 0}^{k}C(k+1,i)0^i1k+1−0k+1=i=0∑k​C(k+1,i)0i

逐项求和可以得到 (n+1)k+1=∑i=0kC(k+1,i)∗S(n,k)\displaystyle (n+1)^{k+1} =\sum_{i=0}^kC(k+1,i)*S(n,k)(n+1)k+1=i=0∑k​C(k+1,i)∗S(n,k),即得到S(n,k)S(n,k)S(n,k)是以 nnn 为自变量的 k+1k + 1k+1 次多项式

令 f(x)=xkf(x) = x^kf(x)=xk,可以得到一个更一般的推广结论:kkk 次多项式的前 nnn 项和 g(n)g(n)g(n) 是一个以 nnn 为自变量的 k+1k + 1k+1 次多项式

回到这题,前k+2k + 2k+2项可以 klog⁡kk \log kklogk 暴力计算,对n≤k+2n \leq k + 2n≤k+2 直接输出答案,对 n>k+2n > k + 2n>k+2 只要插值一下,根据插值公式计算即可。


代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 100;
int n,k;
int x[maxn],y[maxn];                //拉格朗日差值的计算
int fac[maxn],ifac[maxn];           //阶乘的逆元
inline int add(int x, int y) {x += y;if (x >= mod)x -= mod;return x;
}inline int sub(int x, int y) {x -= y;if (x < 0)x += mod;return x;
}inline int mul(int x, int y) {return (long long) x * y % mod;
}
int fpow(int a,int b) {int r = 1;while (b) {if (b & 1) r = mul(r,a);b >>= 1;a = mul(a,a);}return r;
}
int main() {scanf("%d%d",&n,&k);for (int i = 1; i <= k + 2; i++) {            //暴力计算 k + 2 个点,根据这 k + 2个点就可以通过插值唯一确定 k + 1次多项式 x[i] = i;y[i] = add(y[i - 1],fpow(x[i],k));}if (n <= k + 2) {                         //n <= k + 2就直接输出,否则下面的处理会出错 printf("%d\n",y[n]);return 0;}fac[0] = 1;for (int i = 1; i <= k + 2; i++) {         //由于k+2个点x取值连续,预处理阶乘,使复杂度降低到O(k) fac[i] = mul(fac[i - 1],i);}ifac[k + 2] = fpow(fac[k + 2],mod - 2);for (int i = k + 1; i >= 0; i--) {ifac[i] = mul(ifac[i + 1],i + 1);}int tmp = 1;                               //n的倒阶乘 ,同样也是为了加速 for (int i = 1; i <= k + 2; i++) {tmp = mul(tmp,(n - i) % mod);}int ans = 0;for (int i = 1; i <= k + 2; i++) {           //插值迭代,得到 f(n) int t = k + 2 - i;int p = (t & 1) ? -1 : 1;int inv = fpow((n - i) % mod,mod - 2);int res = mul(mul(ifac[i - 1],ifac[t]),mul(tmp,inv));res = mul(mul(res,p),y[i]);if (res < 0) res += mod;ans = add(ans,res);}printf("%d\n",ans);return 0;
}

Codeforce 622 F. The Sum of the k-th Powers(拉格朗日插值求k次幂之和,拉格朗日插值公式)相关推荐

  1. BZOJ 2137 submultiple(约数,拉格朗日插值求自然数k次幂和)【BZOJ 修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2137 是 hydro 的 BZOJ ...

  2. 牛客挑战赛36 D. 排名估算( “概率论全家桶”,好题,拉格朗日插值求自然数 k 次幂之和)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://ac.nowcoder.com/acm/contest/3782/D ...

  3. C语言学习之求∑k(k=100)+∑K*k(k=50)+∑1/k(k=10)

    求∑k(k=100)+∑K*k(k=50)+∑1/k(k=10) #include <stdio.h> #include <math.h> void main(){double ...

  4. F. Cowmpany Cowmpensation(树形dp + 拉格朗日插值)

    F. Cowmpany Cowmpensation 首先一般dp推导dp[i][j]=∏u∈soni∑k=1jdp[v][k]dp[i][j] = \prod\limits_{u \in son_i} ...

  5. 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂

    题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...

  6. 给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除。

    题目描述: 给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除. 输入: 两个整数n(2<=n<=1000),a(2<=a<=1000) 输出: 一个整数. ...

  7. 「CF622F」The Sum of the k-th Powers「拉格朗日插值」

    题意 求\(\sum_{i=1}^n i^k\),\(n \leq 10^9,k \leq 10^6\) 题解 观察可得答案是一个\(k+1\)次多项式,我们找\(k+2\)个值带进去然后拉格朗日插值 ...

  8. nyoj 1261 音痴又音痴的LT(离散化+树状数组求K小数)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1261 解题思路:比较水的题,用离散化+树状数组求K小数即可,先用一次离线处理. #inc ...

  9. poj 2985(并查集+线段树求K大数)

    解题思路:这道题并查集很容易,合并时找到父节点就直接加上去就ok了.关键是如何求K大数,我一直在想用线段树怎么写,一开始想如果直接记录数的大小那肯定是没戏了,借鉴了一下别人的思路:区间[a,b]记录的 ...

最新文章

  1. python读书笔记二、文件基本操作
  2. 通信中的带宽关系、以及码元、波特率、比特率、奈奎斯特带宽
  3. 求中位数_图解面试题:如何分析中位数?
  4. 用apksigner进行批量签名的脚本
  5. P1963 [NOI2009]变换序列
  6. 来自山西机器人乐队_冰山上的机器人X三十禁放映 | 庞宽、李霄云对谈预告
  7. android 遮罩 进度条,bootstrap创建带遮罩层的进度条
  8. linux系列的命令补充
  9. Python椭圆加密算法实现区块链信息认证
  10. Linux 下用yum安装mysql
  11. 大数据分析要避免哪些错误
  12. Map先排序value小->大再排序key小->大,ArrayList与Stream分别实现
  13. java 对错代厔_汉字转拼音源码的两个类
  14. 干货丨Kubernetes 中分析调试网络流量的4种方法
  15. 我就是那菜花!我就是那花椰菜!
  16. 无盘服务器4根网线雨两根网线的区别,网线接法的描述:实际用到4根。
  17. 阿里云OSS对象存储-图文详解
  18. strcat、strcpy、strcmp三种函数用法
  19. 自用推荐,heic格式转换工具
  20. 2021-1-9 吴恩达-C5 序列模型-w2 自然语言处理与词嵌(课后编程1-Operations on word vectors 词向量运算-含UnicodeDecodeError解决)

热门文章

  1. 线索二叉树,画图教你秒懂线索二叉树(线索二叉树的建立和简单操作)逻辑代码分析
  2. 关于duedate补充
  3. 股票API下单接口是怎样传入交易数据的?
  4. llinu启动oracle数据库,RAID与磁盘阵列] USP-V将DS8000虚拟的全过程
  5. 基于Springboot外卖系统05:用户非登陆状态的页面拦截器实现
  6. 以太坊Parity节点搭建
  7. mysql启动提示少vc90.crt_近乎(Spacebuilder) v4.1.0.1源码
  8. python如何解决打不开txt文件的问题(UnicodeDecodeError)
  9. 腾讯云TDSQL数据库信创演进与实践
  10. 走向人生巅峰?这份自由程序员速成宝典你值得拥有...