[TJOI2018]教科书般的亵渎

VIII.[TJOI2018]教科书般的亵渎

这题主要是介绍拉格朗日插值模板那题中,我们提到的“求出f(x)的多项式表达”的做法。

首先,这题显然如果我们令f(x)=i=0xim+1,且am+1=n+1的话,答案就是

i=1m+1j=0i1f(ai1aj)f(ai1aj)

这是由题意可以直接得出的。

于是我们现在重点就在于如何求出f(x),即i=0xim+1

经验告诉我们,这是一个m+2次多项式。于是我们就随便找m+2个点带进去插值一下就能求出这个多项式的系数表达。

当然,这题的瓶颈不在于f(x)的求法,而在于答案那个式子,你无论如何都需要O(n3)秦九韶代入求值,故总复杂度O(n3)。这也意味着你可以图方便直接O(n3)高斯消元消出多项式系数出来。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int T,m,b[100],c[100],d[100],e[100],res;
ll n,a[100];
int ksm(int x,int y){
	int z=1;
	for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)z=1ll*z*x%mod;
	return z;
}
void mul(int x){
	for(int i=m+2;i>=0;i--){
		b[i]=1ll*b[i]*x%mod;
		if(i)(b[i]+=b[i-1])%=mod;
	}
}
void div(int x){
	for(int i=0;i<=m+2;i++)c[i]=b[i];
	for(int i=m+2;i;i--)c[i-1]=(c[i-1]-1ll*c[i]*x%mod+mod)%mod;
	for(int i=0;i<=m+1;i++)c[i]=c[i+1];
}
int func(ll x){
	((x%=mod)+=mod)%=mod;
	int ret=0;
	for(int i=m+1;i>=0;i--)ret=(1ll*ret*x+d[i])%mod;
	return ret;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%lld%d",&n,&m),m++,res=0;
		for(int i=1;i<m;i++)scanf("%lld",&a[i]);
		sort(a+1,a+m);
		b[0]=1;for(int i=1;i<=m+2;i++)b[i]=0;
		for(int i=0;i<=m+1;i++)d[i]=0;
		for(int i=0;i<=m+1;i++)e[i]=ksm(i,m),mul((mod-i)%mod);
		for(int i=1;i<=m+1;i++)(e[i]+=e[i-1])%=mod;
		for(int i=0;i<=m+1;i++){
			div((mod-i)%mod);
			int delta=e[i];
			for(int j=0;j<=m+1;j++)if(i!=j)delta=1ll*delta*ksm((i-j+mod)%mod,mod-2)%mod;
			for(int j=0;j<=m+1;j++)c[j]=1ll*c[j]*delta%mod;
			for(int j=0;j<=m+1;j++)(d[j]+=c[j])%=mod;
		}
		a[m]=n+1;
		for(int i=1;i<=m;i++)for(int j=0;j<i;j++)(res+=(func(a[i]-a[j]-1)-func(a[i-1]-a[j])+mod)%mod)%=mod;
		printf("%d\n",res);
	}
	return 0;
} 

posted @   Troverld  阅读(85)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示