首页 > 其他分享 >拉格朗日插值小应用

拉格朗日插值小应用

时间:2023-02-18 17:12:57浏览次数:48  
标签:拉格朗 插值 text ll int maxn 应用

关于拉格朗日插值:我只会最简单的形式喵。

就是给 \(n\) 个点值,就能在 \(O(n^2)\) 的时间复杂度内求出当 \(x=a\) 的时候的值。

其标准形式是:\(\displaystyle \sum_{i=1}^n y_i \prod _{j\not =i}^n \frac{a-x_j}{x_i-x_j}\)

然后它更高深的应用我暂时不会喵。

但是也许能用在一些小清新 DP 式的优化。

主要在于如果发现式子有一个消不掉的巨大数字,并且能够确定整个结果是和它有关的多项式,就能先求出小值域下的结果,然后再插值回去。

CF995F Cowmpany Cowmpensation

题意:\(n\) 个点的树,给每个点分配权值 \([1,d]\),父亲的权值必须大于儿子,求方案数。

\(f_{i,j}\) 表示整棵树的权值在 \(1\sim j\) 的方案数。

\(\displaystyle f_{p,i}=f_{p,i-1}+\prod_{v\in p} f_{v,i}\)

所有叶子的 \(f_{p,i}=i\)

感性理解一下,当在叶子上时,\(f_{p,i}\) 是一个关于 \(i\) 的一次函数,也就是多项式的项数为 \(2\) 。而考虑叶子们的父亲,就是把儿子们乘起来,变成了次数为叶子数加一的多项式。也就是说,到根的时候,最多是一个关于 \(i\),项数为 \(n\) 次的多项式。这样可以 \(n^2\) 求出一部分点值,再拉格朗日插值把 \(d\) 带进去。

#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
ll ksm(ll x,ll y)
{
	ll ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%mod;
		x=x*x%mod; y>>=1;
	}
	return ret;
}
int n,D;
const int maxn=6005;
int to[maxn],nxt[maxn],head[maxn],num;
void add(int x,int y){num++;to[num]=y;nxt[num]=head[x];head[x]=num;}
ll f[3002][3002],a[maxn],b[maxn];
void dfs(int p,int fa)
{
	for(int i=head[p];i;i=nxt[i])
	{
		if(to[i]==fa) continue;
		dfs(to[i],p); 
	}
	for(int j=1;j<=n;j++)
	{
		ll ret=1;
		for(int i=head[p];i;i=nxt[i])
			if(to[i]!=fa) ret=ret*f[to[i]][j]%mod;
		f[p][j]=(f[p][j-1]+ret)%mod;
	}
}
ll LA(int n,int D,ll *a,ll *b)
{
	ll ret=0;
	for(int i=0;i<=n;i++) 
	{
		ll x1=1,x2=1;
		for(int j=0;j<=n;j++)
		{
			if(i==j) continue;
			x1=x1*(D-a[j])%mod; x2=x2*(a[i]-a[j])%mod;
		}
		ret=(ret+x1*ksm(x2,mod-2)%mod*b[i]%mod)%mod;
	}
	return (ret%mod+mod)%mod;
}
int main()
{
	scanf("%d%d",&n,&D);
	for(int i=2;i<=n;i++)
	{
		int f; scanf("%d",&f);
		add(f,i);
	}
	dfs(1,0);
	for(int i=0;i<=n;i++) a[i]=i,b[i]=f[1][i];
	printf("%lld\n",LA(n,D,a,b));
}

[省选联考 2022] 填树

首先题面善良地告诉你被染色的点是一条链。

那么很容易写出第一问的转移方程。

枚举最小值为 \(L\),当前情况下的答案为 \(A_{L}\),设 \(f_{p}\) 表示以 \(p\) 为根,所有符合条件的链的数量,\(\displaystyle f_{i}=(b_i-a_i+1)\prod_{v \in son} f_v\)。

\(a_i,b_i\) 表示在整棵树上最小值为 \(L\) 的情况下,\(i\) 节点能到达的值域。\(a_i=\max\{l_i,L\},b_i=\min\{r_i,L+K-1\}\),如果 \(a_i>b_i\) 则 \(f_i=0\)。

然后在每个点上合并儿子的时候算一下当前链和前面已经合并的 \(f_i\) 匹配一下,统计到总答案里。

那么 \(A_L=f_{1}-A_{L-1}\) 。这样减一下是因为 \(f_{i}\) 可能统计重复,就是没有最小值取到 \(L\) 的情况。

然后我们猜测 \(A_{L}\) 可能是关于 \(L\) 的,项数为 \(n+1\) 的多项式。因为可以发现最终答案就是两条链 \(b_i-a_i+1\) 乘到一起然后在 \(lca\) 处加起来的,而 \(b_i-a_i+1\) 是关于 \(L\) 的一次函数,假设 \(b_i-a_i+1=len_i\),\(len_i\) 与 \(L\) 有如下关系:

\(len_i=\begin{cases}0 &\text{if } L+K-1<l_i&\text{or } L>r_i\\L+K-l_i &\text{if } L+K-1\geq l_i &\text{and } l_i \leq L\leq r_i\\ K &\text{if } L\geq l_i &\text{and } L+K-1 \leq r_i\\r_i-L+1 &\text{if }l_i\leq L\leq r_i&\text{and } L+K-1\geq r_i \end{cases}\)

上面就是为了向你展示 \(L\) 与每个点乘进去的权值的一次函数关系。

所以 \(A_L\) 是关于 \(L\) 的 \(n+1\) 项的多项式,不过每一项系数可能随 \(L\) 的大小改变。

但是如果我们把它想象成函数图像,就会明白能够使它发生转折的只有大约 \(O(n)\) 个点,剩下的时候都是连续的函数。那么我们就可以考虑拉格朗日插值:我们找到所有可能使函数转折横坐标,将它排序之后一段一段地考虑当前的函数。假如当前这段的函数图像覆盖的范围不太大(小于等于 \(n\)),那么我们完全可以把这段里所有的函数值全求出来加和;而如果覆盖的范围很大,我们求出这一段的前 \(n\) 个点值,然后做一个前缀和,再用结尾的横坐标做拉格朗日插值,得到的数字相当于这一段的和。对于每一段的函数都求出来所有的和,那么总的和就是答案啦。

标签:拉格朗,插值,text,ll,int,maxn,应用
From: https://www.cnblogs.com/cc0000/p/17133059.html

相关文章

  • Linux配置应用自启动,碰到一些问题
    最近在搞一个arm-linux,发现自动运行与手动运行,竟然效果是不一样,在解决问题的同时,也顺便把Linux启动相关一些知识梳理一遍。 问题1:在/etc/init.d/新建一个S90startapp......
  • 高CPU Java应用分析
    模拟CPU40%左右importjava.util.concurrent.CountDownLatch;publicclassMainextendsThread{privateCountDownLatchc;publicMain(Stringname,Cou......
  • 关于 Angular Universal 应用执行时需要 Browser API 的问题
    由于AngularUniversalApplication不在浏览器中执行,因此服务器上可能缺少某些浏览器API和功能。例如,服务器端应用程序不能引用仅供浏览器使用的全局对象,例如Window,Do......
  • 人大金仓数据库索引的应用与日常运维
    索引的应用一、常见索引及适应场景BTREE索引是KES默认索引,采用B+树实现。适用场景范围查询和优化排序操作。不支持特别长的字段。HASH索引先对索引列计算一个散列值(类似md5......
  • Edgio赞助OWASP ModSecurity CRS,进一步推动以OWASP核心规则集为基础的高级应用安全发
    亚利桑那州凤凰城,2023年2月2日—EdgioInc.(纳斯达克:EGIO),作为以速度、安全性和易用性著称的首选平台,Edgio今天宣布成为开放网络应用安全项目(OWASP)下,ModSecurity核心规则集......
  • Spring Boot Redis 应用场景
    1.前言Redis其实就是基于内存的键值型数据库,与Oracle、SQLServer、MySQL等传统关系型数据库相比,它最大的优势就是读写速度快。到底有多快呢,我曾经使用Windows版......
  • 如何在 C++ 应用程序中集成 Spire.XLS for C++
    Spire.XLSforC++ 是一个Excel库,供开发人员在任何类型的C++应用程序中操作Excel文档(XLS、XLSX、XLSB和XLSM)。本文演示了如何以两种不同的方式将Spire.XLSforC......
  • 学习APT以及简单应用( 注解实现 findViewById)
    本文的参考资料、原代码都可以在享学课堂中获取/***创建JavaLibraryModule名称为APTModule*1、创建自定义注解MQBindView*2、创建注解处理器MQProcessor*3......
  • 4.打包子应用 投票
    接上回最终得到这样的目录mysite/manage.pymysite/__init__.pysettings.pyurls.pyasgi.pywsgi.pypolls/......
  • 使用Docker启动并运行Flask应用
    (一)拉取Python镜像dockerpullpython#查看当前主机中存在的镜像dockerimages(二)编写flask应用1.创建一个目录mkdirflask_demo#进入目录中cdflask_de......