【LOJ #2289】「THUWC 2017」在美妙的数学王国中畅游(LCT+泰勒展开)

传送门

首先显然 e x e^x ex s i n sin sin都不好维护整体
发现他给你了个提示
那么显然就是要用的了
那么就可以直接把 e e e s i n sin sin x = 0 x=0 x=0
展开展开个十几项
由于有除以阶乘所以后面的就小到可以忽略不计了
其中
e a x + b = ∑ i e b ( a x ) i i ! e^{ax+b}=\sum_{i}\frac{e^b(ax)^i}{i!} eax+b=ii!eb(ax)i
s i n ( a x + b ) = ∑ i f ( i ) ( b ) ( a x ) i i ! sin(ax+b)=\sum_{i} \frac{f^{(i)}(b)(ax)^i}{i!} sin(ax+b)=ii!f(i)(b)(ax)i
s i n ( x ) ′ = c o s ( x ) sin(x)'=cos(x) sin(x)=cos(x)
c o s ( x ) ′ = − s i n ( x ) cos(x)'=-sin(x) cos(x)=sin(x)

然后维护即可

用数组维护多项式比用 v e c t o r vector vector快了一倍。。。

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re regitster
#define pb push_back
#define fi first
#define se second
#define pii pair<int,int>
#define ll long long
#define bg begin
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0;bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
inline void readstring(char *s){
	int top=0;
	char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
#define poly vector<double>
cs int N=100005,Lim=16;
inline void Plus(double *a,double *b){
	for(int i=0;i<Lim;i++)
	a[i]+=b[i];
}
inline double F(double *a,double x){
	double ret=0,mt=1;
	for(int i=0;i<Lim;i++,mt*=x)ret+=a[i]*mt;
	return ret;
}
double fac[Lim];
inline void init_fac(){
	fac[0]=1;
	for(int i=1;i<Lim;i++)fac[i]=fac[i-1]*i;
}
inline void getval(double *ret,int op,double f1,double f2){
	double mt=1;
	for(int i=0;i<Lim;i++)ret[i]=0;
	if(op==1){
		double c1=sin(f2),c2=cos(f2);
		for(int i=0;i<Lim;i++,mt*=f1){
			switch(i%4){
				case 0:ret[i]=(c1*mt/fac[i]);break;
				case 1:ret[i]=(c2*mt/fac[i]);break;
				case 2:ret[i]=(-c1*mt/fac[i]);break;
				case 3:ret[i]=(-c2*mt/fac[i]);break;
			}
		}
	}
	else if(op==2){
		double c=exp(f2);
		for(int i=0;i<Lim;i++,mt*=f1){
			ret[i]=(c*mt/fac[i]);
		}
	}
	else{
		ret[0]=f2,ret[1]=f1;
	}
}
namespace Lct{
	double val[N][16],s[N][16];
	int son[N][2],rev[N],fa[N];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	inline void pushup(int u){
		for(int i=0;i<Lim;i++)s[u][i]=val[u][i];
		if(lc(u))Plus(s[u],s[lc(u)]);
		if(rc(u))Plus(s[u],s[rc(u)]);
	}
	inline void pushrev(int u){
		swap(lc(u),rc(u)),rev[u]^=1;
	}
	inline void pushdown(int u){
		if(!rev[u])return;
		if(lc(u))pushrev(lc(u));
		if(rc(u))pushrev(rc(u));
		rev[u]=0;
	}
	inline bool isrt(int u){
		return !fa[u]||(lc(fa[u])!=u&&rc(fa[u])!=u);
	}
	inline bool isrc(int u){
		return rc(fa[u])==u;
	}
	inline void init(int u,int op,double f1,double f2){
		getval(val[u],op,f1,f2),pushup(u);
	}
	inline void rotate(int v){
		int u=fa[v],z=fa[u];
		int t=isrc(v);
		if(!isrt(u))son[z][isrc(u)]=v;
		fa[v]=z;
		fa[son[v][t^1]]=u;
		son[u][t]=son[v][t^1];
		fa[u]=v,son[v][t^1]=u;
		pushup(u),pushup(v);
	}
	int stk[N],top;
	inline void splay(int u){
		stk[top=1]=u;
		for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
		for(int i=top;i;i--)pushdown(stk[i]);
		while(!isrt(u)){
			if(!isrt(fa[u]))
			isrc(fa[u])==isrc(u)?rotate(fa[u]):rotate(u);
			rotate(u);
		}
	}
	inline void access(int u){
		for(int v=0;u;v=u,u=fa[u]){
			splay(u);
			rc(u)=v;
			pushup(u);
		}
	}
	inline int findrt(int u){
		access(u),splay(u);
		while(pushdown(u),lc(u))u=lc(u);splay(u);
		return u;
	}
	inline void makert(int u){
		access(u),splay(u),pushrev(u);
	}
	inline void link(int u,int v){
		makert(u),access(v),splay(v),fa[u]=v,pushup(v);
	}
	inline void cut(int u,int v){
		makert(u),access(v),splay(v);
		lc(v)=fa[u]=0,pushup(v);
	}
	inline void update(int u,int op,double f1,double f2){
		access(u),splay(u),getval(val[u],op,f1,f2),pushup(u);
	}
	inline double query(int u,int v,double x){
		makert(u),access(v),splay(v);
		return F(s[v],x);
	}
}
int n,m;
char s[N];
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m=read();
	readstring(s);
	init_fac();
	double f1,f2;
	for(int i=1;i<=n;i++){
		int op=read();
		scanf("%lf%lf",&f1,&f2);
		Lct::init(i,op,f1,f2);
	}
	for(int i=1,u,v;i<=m;i++){
		readstring(s);
		u=read(),v=read();
		switch(s[1]){
			case 'a':Lct::link(u+1,v+1);break;
			case 'd':Lct::cut(u+1,v+1);break;
			case 't':{
				scanf("%lf",&f1),u++,v++;
				if(Lct::findrt(u)!=Lct::findrt(v)){puts("unreachable");}
				else printf("%.10lf\n",Lct::query(u,v,f1));
				break;
			}
			case 'm':{
				scanf("%lf%lf",&f1,&f2);
				Lct::update(u+1,v,f1,f2);
				break;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值