一眼$LCT$,然而乍一看一堆函数求和没得搞。
题目下面给出了泰勒展开的式子。于是可以对$\sin(ax+b)$和$e^{ax+b}$泰勒展开,用多项式拟合函数。
先求个导:
- $(\sin(ax+b))^{(n)}=\begin{cases}a^n\sin(ax+b)&n\bmod4=0\\a^n\cos(ax+b)&n\bmod4=1\\ -a^n\sin(ax+b)&n\bmod4=2\\ -a^n\cos(ax+b)&n\bmod4=3\end{cases}$
- $(e^{ax+b})^{(n)}=a^ne^{ax+b}$
至于$\xi,x_0$的取值,代个$0$就很方便。
现在要搞的就是一堆多项式求和,直接系数相加就能维护了。
由于分母上是阶乘,增长非常快,实测展开到$11$次项就能过。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 100005
#define inf 0x3f3f3f3f
#define tp 11
using namespace std;
inline int read(){
int x=0,y=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return y?-x:x;
}
struct Poly{
double c[tp+1];
Poly(int t=3,double a=0,double b=0){
if(t==1){
double S=sin(b),C=cos(b),base=1;
for(register int i=0;i<=tp;i+=2,S=-S,C=-C)c[i]=base*S,base*=a,c[i+1]=base*C,base*=a;
}
else if(t==2){
double e=exp(b),base=1;
for(register int i=0;i<=tp;++i)c[i]=e*base,base*=a;
}
else{
c[0]=b,c[1]=a;
for(register int i=2;i<=tp;++i)c[i]=0;
}
}
Poly operator + (const Poly &x){
Poly ans;
for(register int i=0;i<=tp;++i)ans.c[i]=c[i]+x.c[i];
return ans;
}
}sum[maxn],dat[maxn];
#define son(x,y) son[x][y]
#define ls(x) son(x,0)
#define rs(x) son(x,1)
#define whson(x) (son(fa[x],1)==x)
#define root(x) (son(fa[x],0)!=x&&son(fa[x],1)!=x)
int son[maxn][2],fa[maxn],rev[maxn];
inline void update(int node){sum[node]=sum[ls(node)]+sum[rs(node)]+dat[node];}
inline void adde(int s,int f,bool wh){
if(s)fa[s]=f;
son(f,wh)=s;
}
inline void rotate(int x){
int f=fa[x],gf=fa[f],wh=whson(x);
if(!root(f))son(gf,whson(f))=x;
fa[x]=gf;
adde(son(x,wh^1),f,wh);
adde(f,x,wh^1);
update(f),update(x);
}
inline void rever(int node){
swap(ls(node),rs(node));
rev[node]^=1;
}
inline void pushdown(int node){
if(rev[node]){
if(ls(node))rever(ls(node));
if(rs(node))rever(rs(node));
rev[node]=0;
}
}
inline void pushtag(int node){
if(!root(node))pushtag(fa[node]);
pushdown(node);
}
inline void splay(int x){
pushtag(x);
int y;
while(!root(x)){
y=fa[x];
if(!root(y))rotate(whson(x)^whson(y)?x:y);
rotate(x);
}
}
void access(int x){
for(register int y=0;x;y=x,x=fa[x])
splay(x),rs(x)=y,update(x);
}
void makeroot(int x){
access(x),splay(x),rever(x);
}
int findroot(int x){
access(x),splay(x);
while(ls(x))pushdown(x),x=ls(x);
splay(x);
return x;
}
void link(int x,int y){
makeroot(x),fa[x]=y;
}
void cut(int x,int y){
makeroot(x),access(y),splay(y);
fa[x]=ls(y)=0,update(y);
}
void modify(int x,int t,double a,double b){
splay(x),dat[x]=Poly(t,a,b),update(x);
}
void query(int x,int y,double z){
makeroot(x);
if(findroot(y)!=x){puts("unreachable");return;}
splay(y);
double ans=0,base=1,fac=1;
for(register int i=0;i<=tp;++i,fac*=i)ans+=base*sum[y].c[i]/fac,base*=z;
printf("%.9lf\n",ans);
}
int main(){
int n=read(),m=read(),x,y;
double a,b;
char s[10];
scanf("%s",s);
for(register int i=1;i<=n;++i){
x=read();
scanf("%lf%lf",&a,&b);
dat[i]=sum[i]=Poly(x,a,b);
}
while(m--){
scanf("%s",s),x=read(),y=read();
if(s[0]=='a')link(x+1,y+1);
else if(s[0]=='d')cut(x+1,y+1);
else if(s[0]=='m')scanf("%lf%lf",&a,&b),modify(x+1,y,a,b);
else scanf("%lf",&a),query(x+1,y+1,a);
}
}