LG4781 【模板】拉格朗日插值 和 JLOI2016 成绩比较
【模板】拉格朗日插值
题目描述
由小学知识可知,$n$个点$(x_i,y_i)$可以唯一地确定一个多项式
现在,给定$n$个点,请你确定这个多项式,并将$k$代入求值
求出的值对$998244353$取模
说明
$n \leq 2000 \; \; \; x_i,y_i,k \leq 998244353$
自为风月马前卒的分析
拉格朗日插值法
众所周知,\(n + 1\)个\(x\)坐标不同的点可以确定唯一的最高为\(n\)次的多项式。在算法竞赛中,我们常常会碰到一类题目,题目中直接或间接的给出了\(n+1\)个点,让我们求由这些点构成的多项式在某一位置的取值
一个最显然的思路就是直接高斯消元求出多项式的系数,但是这样做复杂度巨大\((n^3)\)且根据算法实现不同往往会存在精度问题
而拉格朗日插值法可以在\(n^2\)的复杂度内完美解决上述问题
假设该多项式为\(f(x)\), 第\(i\)个点的坐标为\((x_i, y_i)\),我们需要找到该多项式在\(k\)点的取值
根据拉格朗日插值法
\]
乍一看可能不是很好理解,我们来举个例子理解一下
假设给出的三个点为\((1, 3)(2, 7)(3, 13)\)
直接把\(f(k)展开\)
\(f(k) = 3 \frac{(k - 2)(k - 3)}{(1 - 2)(1 - 3)} + 7\frac{(k-1)(k-2)}{(2 - 1)(2-3)} + 13\frac{(k-1)(k-2)}{(3 -1)(3-2)}\)
观察不难得到,如果我们把\(x_i\)带入的话,除第\(i\)项外的每一项的分子中都会有\(x_i - x_i\),这样其他的所有项就都被消去了
因此拉格朗日插值法的正确性是可以保证的
下面说一下拉格朗日插值法的拓展
在\(x\)取值连续时的做法
在绝大多数题目中我们需要用到的\(x_i\)的取值都是连续的,这样的话我们可以把上面的算法优化到\(O(n)\)复杂度
首先把\(x_i\)换成\(i\),新的式子为
\(f(k) = \sum_{i=0}^n y_i \prod_{i \not = j} \frac{k - j}{i - j}\)
考虑如何快速计算\(\prod_{i \not = j} \frac{k - j}{i - j}\)
对于分子来说,我们维护出关于\(k\)的前缀积和后缀积,也就是
\]
\]
对于分母来说,观察发现这其实就是阶乘的形式,我们用\(fac[i]\)来表示\(i!\)
那么式子就变成了
\]
注意:分母可能会出现符号问题,也就是说,当\(N - i\)为奇数时,分母应该取负号
重心拉格朗日插值法
再来看一下前面的式子
\]
设\(g = \prod_{i=0}^n k - x[i]\)
\]
设\(t_i = \frac{y_i}{\prod_{j \not =i} x_i - x_j}\)
\]
这样每次新加入一个点的时候只需要计算它的\(t_i\)即可
应用
首先讲一个经典应用:计算\(\sum_{i=1}^n i^k (n \leqslant 10^{15}, k \leqslant 10^6)\)
老祖宗告诉我们,这个东西是个以\(n\)为自变量的\(k + 1\)次多项式,具体证明可以看第二份参考资料
然后直接带入\(k+1\)个点后用拉格朗日插值算即可,复杂度\(O(k)\)
那具体在题目中怎么使用拉格朗日插值呢?
首先你要证明求的东西是某个多项式,判断的依据是:
大部分情况下归纳一下就可以了
时间复杂度\(O(n^2)\)
int n,k,x[N],y[N];
int main(){
read(n),read(k);
for(int i=1;i<=n;++i) read(x[i]),read(y[i]);
int ans=0;
for(int i=1;i<=n;++i){
int val=1;
for(int j=1;j<=n;++j)if(j!=i) val=mul(val,add(x[i],mod-x[j]));
val=mul(y[i],fpow(val,mod-2));
for(int j=1;j<=n;++j)if(j!=i) val=mul(val,add(k,mod-x[j]));
ans=add(ans,val);
}
printf("%d\n",ans);
return 0;
}
成绩比较
有n个人m门学科,第i门的分数为不大于Ui的一个正整数
定义A「打爆」B当且仅当A的每门学科的分数都不低于B的该门学科的分数
已知第一个人第i们学科的排名为Ri,
即这门学科不低于n−Ri人的分数,但一定低于Ri−1人的分数
求有多少种方案使得第一个人恰好「打爆」了k个人
两种方案不同当且仅当存在两个人的分数不同
n,m≤100,Ui≤109
梦的题解
首先容斥
设\(g_x\)表示第一个人至少「打爆」了\(x\)个人的方案数,
\(A_i\)表示给所有人第\(i\)门学科分配分数使得第一个人排名正确的方案数,有
\]
\]
\(g_x\)的意义是:先选出被吊打的\(x\)个人,再枚举每一门学科,这门学科比\(n-R_i\)人高。除去被吊打的\(x\)人外还需要在未被吊打的\(n-x-1\)人中选出\(n-R_i-x\)人这门比第一个人低,然后再给这\(n\)个人分配分数。
\(A_i\)的意义是:枚举第一个人第\(i\)门的分数\(j\),有\(n-R_i\)人分数不能高于\(j\),其余\(R_i-1\)人分数必须高于\(j\)。
容易发现瓶颈在快速计算$ A_i$上
我们将\(A_i\)二项式展开得
=\sum\limits_{j=1}^{U_i}j^{n-R_i}\sum\limits_{k=0}^{R_i-1} \binom{R_i-1}{k}{(U_i)}^k(-j)^{R_i-k-1}\\
=\sum\limits_{k=0}^{R_i-1} \binom{R_i-1}{k}{(U_i)}^k\sum\limits_{j=1}^{U_i}j^{n-R_i}(-j)^{R_i-k-1}\\
=\sum\limits_{k=0}^{R_i-1} \binom{R_i-1}{k}{(U_i)}^k(-1)^{R_i-k-1}\sum\limits_{j=1}^{U_i}j^{n-k-1}
\]
前半部分非常好算,后半部分是一个自然数幂和,可以拉格朗日插值解决
拉格朗日插值过程中可以通过预处理前后缀的方式去掉不必要的求逆元复杂度使除预处理外单次\(O(n)\)。
这样就可以快速算出\(g_x\)了。
然后就是喜闻乐见的二项式反演环节
设\(f_x\)表示第一个人恰好「打爆」了$ x$个人
有
\]
\]
然后这道题就解决了,总复杂度:\(O(n^2m)\)
co int N=100+10;
int fac[N],ifac[N];
int sp[N][N]; // the sum of the ith power of 1~j
il int binom(int n,int m){
return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int calc(int n,int k){
if(!k) return n;
if(n<N) return sp[k][n];
static int pre[N],suf[N];
pre[0]=1;
for(int i=1;i<=k+2;++i) pre[i]=mul(pre[i-1],n-i);
suf[k+3]=1;
for(int i=k+2;i>=1;--i) suf[i]=mul(suf[i+1],n-i);
int ans=0;
for(int i=1;i<=k+2;++i){
int down=mul(ifac[i-1],ifac[k+2-i]);
if((k+2-i)&1) down=mod-down;
ans=add(ans,mul(sp[k][i],mul(pre[i-1],mul(suf[i+1],down))));
}
return ans;
}
int U[N],R[N];
int A[N],g[N];
int main(){
fac[0]=1;
for(int i=1;i<N;++i) fac[i]=mul(fac[i-1],i);
ifac[N-1]=fpow(fac[N-1],mod-2);
for(int i=N-2;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
for(int i=1;i<N;++i)
for(int j=1;j<N;++j) sp[i][j]=add(sp[i][j-1],fpow(j,i));
int n=read<int>(),m=read<int>(),K=read<int>();
for(int i=1;i<=m;++i) read(U[i]);
for(int i=1;i<=m;++i) read(R[i]);
for(int i=1;i<=m;++i)
for(int k=0;k<=R[i]-1;++k){
int sum=mul(binom(R[i]-1,k),mul(fpow(U[i],k),calc(U[i],n-k-1)));
A[i]=add(A[i],(R[i]-k-1)&1?mod-sum:sum);
}
for(int i=1;i<n;++i){
g[i]=binom(n-1,i);
for(int j=1;j<=m;++j){
if(n-i-R[j]<0) {g[i]=0;break;}
g[i]=mul(g[i],mul(binom(n-i-1,n-i-R[j]),A[j]));
}
}
int ans=0;
for(int i=K;i<=n;++i){
int sum=mul(binom(i,K),g[i]);
ans=add(ans,(i-K)&1?mod-sum:sum);
}
printf("%d\n",ans);
return 0;
}
LG4781 【模板】拉格朗日插值 和 JLOI2016 成绩比较的更多相关文章
- CF622F——自然数幂和模板&&拉格朗日插值
题意 求 $ \displaystyle \sum_{i=1}^n i^k \ mod (1e9+7), n \leq 10^9, k \leq 10^6$. CF622F 分析 易知答案是一个 $k ...
- LG4781 【模板】拉格朗日插值
题意 题目描述 由小学知识可知,$n$个点$(x_i,y_i)$可以唯一地确定一个多项式 现在,给定$n$个点,请你确定这个多项式,并将$k$代入求值 求出的值对$998244353$取模 输入输出格 ...
- bzoj千题计划270:bzoj4559: [JLoi2016]成绩比较(拉格朗日插值)
http://www.lydsy.com/JudgeOnline/problem.php?id=4559 f[i][j] 表示前i门课,有j个人没有被碾压的方案数 g[i] 表示第i门课,满足B神排名 ...
- BZOJ4599[JLoi2016&LNoi2016]成绩比较(dp+拉格朗日插值)
这个题我们首先可以dp,f[i][j]表示前i个科目恰好碾压了j个人的方案数,然后进行转移.我们先不考虑每个人的分数,先只关心和B的相对大小关系.我们设R[i]为第i科比B分数少的人数,则有f[i][ ...
- bzoj 4559 [JLoi2016]成绩比较 —— DP+拉格朗日插值
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4559 看了看拉格朗日插值:http://www.cnblogs.com/ECJTUACM-8 ...
- P3270 [JLOI2016]成绩比较 容斥 数论 组合数学 拉格朗日插值
LINK:成绩比较 大体思路不再赘述 这里只说几个我犯错的地方. 拉格朗日插值的时候 明明是n次多项式 我只带了n个值进去 导致一直GG. 拉格朗日插值的时候 由于是从1开始的 所以分母是\((i-1 ...
- BZOJ.4559.[JLOI2016]成绩比较(DP/容斥 拉格朗日插值)
BZOJ 洛谷 为什么已经9点了...我写了多久... 求方案数,考虑DP... \(f[i][j]\)表示到第\(i\)门课,还有\(j\)人会被碾压的方案数. 那么\[f[i][j]=\sum_{ ...
- 【BZOJ】4559: [JLoi2016]成绩比较 计数DP+排列组合+拉格朗日插值
[题意]n位同学(其中一位是B神),m门必修课,每门必修课的分数是[1,Ui].B神碾压了k位同学(所有课分数<=B神),且第x门课有rx-1位同学的分数高于B神,求满足条件的分数情况数.当有一 ...
- bzoj 4559 [JLoi2016]成绩比较——拉格朗日插值
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4559 关于拉格朗日插值,可以看这些博客: https://www.cnblogs.com/E ...
随机推荐
- IDEA和JIRA任务联动(redmine同理)
IDEA和JIRA任务联动-操作流程详解 redmine和这个步骤类似,只是第一步选择的工具不一样 操作流程 添加jira配置,File->Setting-->tools-->Tas ...
- 【bat】【windows】win10查看所有wifi密码
win10的可以,win7的好像不行 @echo off & setlocal EnableDelayedExpansion title 查看所有wifi和密码 for /f "us ...
- 基于Livy的Spark提交平台搭建与开发
为了方便使用Spark的同学提交任务以及加强任务管理等原因,经调研采用Livy比较靠谱,下图大致罗列一下几种提交平台的差别. 本文会以基于mac的单机环境搭建一套Spark+Livy+Hadoop来展 ...
- 小程序onShow
/** * 生命周期函数--监听页面加载 */ onLoad: function(options) { let that = this; const openid = app.globalData.o ...
- Java打开GC日志
环境: JDK1.8 打开GC日志: -verbose:gc 这个只会显示总的GC堆的变化, 如下: [GC (Allocation Failure) 80832K->19298K(2278 ...
- python笔记:删除列表元素和根据索引查找元素
查找元素 #查找元素 >>> member=['张三','李四','王五','张麻子'] >>> member[0] '张三' #交换元素 >>> ...
- c# EF插入数据报错跟踪代码
我们在使用EF进行数据库插入的时候或出现一些插入失败的情况,但是具体是哪个字段不符合数据库设计要求无法得知,普通的try catch 无法捕获加上一下方法就可以 try { ...
- delphi xe10 FMX 启动参数
关于 Delphi Xe10 FMX 启动参数 需要在启动窗口前来调用 也就是在bar文件修改 如果参数多可以用json来 uses system.SysUtils; var param: stri ...
- ArcGIS Engine开发鹰眼图的功能(基础篇)
鹰眼是用于调节全视域范围内主地图显示范围情况的副地图.它体现了地图整体与详细局部的关系. 用户可以通过鼠标单击或者画框等动作实现鹰眼与主地图的交互情况. 鹰眼功能的原理是通过主地图窗口的地图控件和鹰眼 ...
- CSP J/S 2019受虐记
一枚蒟蒻的游记~ 提高组DAY1 不是说每场考试都有一道签到题吗 那我tm读了三遍题硬是没找到一道水题是怎么回事(是我太弱了吗) 没办法,硬着头皮做T1 暴力写法...期望得分30pts 于是...在 ...