BZOJ传送门
洛谷传送门
解析:
题目下方有一个提示。就是泰勒展开。
不过这道题的泰勒展开还算简单。
思路:
泰勒展开能够让我们将误差控制在一定范围的同时,快速维护多个函数的和。
主要思想是将非多项式函数拆成多项式维护每一项的系数。
如果对导数不是很了解的话可以看一下这篇博客:https://blog.csdn.net/qq_35649707/article/details/74611460
当然如果您现在不是很想了解的话,就记几个结论吧:
( a x ) ′ = a x ∗ ln a (a^x)'=a^x*\ln a (ax)′=ax∗lna
特别的,我们有: ( e x ) ′ = e x (e^x)'=e^x (ex)′=ex
三角函数的求导: cos ( x ) ′ = − sin ( x ) \cos(x)'=-\sin(x) cos(x)′=−sin(x) sin ( x ) ′ = cos ( x ) \sin(x)'=\cos(x) sin(x)′=cos(x)
显然变化周期为 4 4 4。
然后就是复合函数的求导: [ f ( g ( x ) ) ] ′ = g ′ ( x ) ∗ f ′ ( g ( x ) ) [f\big(g(x)\big)]'=g'(x)*f'(g(x)) [f(g(x))]′=g′(x)∗f′(g(x))
放到这道题上,展开前面
sin
\sin
sin函数,我们就能得到:
sin
′
(
a
x
+
b
)
=
a
cos
(
a
x
+
b
)
\sin'(ax+b)=a\cos(ax+b)
sin′(ax+b)=acos(ax+b)
sin
′
′
(
a
x
+
b
)
=
−
a
2
sin
(
a
x
+
b
)
\sin''(ax+b)=-a^2\sin(ax+b)
sin′′(ax+b)=−a2sin(ax+b)
sin
′
′
′
(
a
x
+
b
)
=
−
a
3
cos
(
a
x
+
b
)
\sin'''(ax+b)=-a^3\cos(ax+b)
sin′′′(ax+b)=−a3cos(ax+b)
维护11项精度就足够了(因为泰勒展开里面除了一个阶乘)
对于
e
x
e^x
ex:
(
e
a
x
+
b
)
(
n
)
=
a
n
e
a
x
+
b
(e^{ax+b})^{(n)}=a^ne^{ax+b}
(eax+b)(n)=aneax+b
展开后LCT维护就是了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<18|1;
char buf[Rlen],*p1,*p2;
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline double getdb(){
re char c;
re bool f=0;
while(!isdigit(c=gc()))if(c=='-')f=1;re double x=c^48;
while(isdigit(c=gc()))x=x*10+(c^48);
if(c!='.')return f?-x:x;
re double y=1.0;
while(isdigit(c=gc()))x+=(y/=10)*(c^48);
return f?-x:x;
}
inline char getop(){
re char c;
while(isspace(c=gc()));return c;
}
}
using namespace IO;
cs int N=100005,M=11;
int n,m;
int fa[N],son[N][2];
bool rev[N];
double coef[N][M+1],sum[N][M+1];
ll fac[M];
inline bool which(int now){return son[fa[now]][1]==now;}
inline bool isroot(int now){return !fa[now]||(son[fa[now]][0]!=now&&son[fa[now]][1]!=now);}
inline void pushup(int now){
for(int re i=0;i<=M;++i)
sum[now][i]=coef[now][i]+sum[son[now][0]][i]+sum[son[now][1]][i];
}
inline void pushdown(int now){
if(rev[now]){
rev[now]=0;
swap(son[now][0],son[now][1]);
if(son[now][0])rev[son[now][0]]^=1;
if(son[now][1])rev[son[now][1]]^=1;
}
}
inline void Rotate(int now){
re int Fa=fa[now],FA=fa[Fa];
re bool pos=which(now);
if(FA&&!isroot(Fa))son[FA][which(Fa)]=now;
son[Fa][pos]=son[now][!pos];
if(son[Fa][pos])fa[son[Fa][pos]]=Fa;
son[now][!pos]=Fa;
fa[Fa]=now;
fa[now]=FA;
pushup(Fa);
pushup(now);
}
inline void Splay(int now){
static int q[N],qn;
q[qn=1]=now;
for(int re Fa=now;!isroot(Fa);Fa=fa[Fa])q[++qn]=fa[Fa];
while(qn)pushdown(q[qn--]);
for(int re Fa;!isroot(now);Rotate(now))
if(!isroot(Fa=fa[now]))Rotate(which(Fa)==which(now)?Fa:now);
}
inline void access(int now){
for(int re ch=0;now;ch=now,now=fa[now])
Splay(now),son[now][1]=ch,pushup(now);
}
inline void makeroot(int now){
access(now);
Splay(now);
rev[now]^=1;
}
inline int findroot(int now){
access(now);
Splay(now);
while(son[now][0])now=son[now][0];
Splay(now);
return now;
}
inline void link(int u,int v){
makeroot(u);fa[u]=v;
}
inline void cut(int u,int v){
makeroot(u);
access(v);
Splay(v);
fa[u]=son[v][0]=0;
pushup(v);
}
inline void Set(int now,int typ,double a,double b){
memset(coef[now],0,sizeof coef[now]);
switch(typ){
case 1:{
re double o=1,Sin=sin(b),Cos=cos(b);
for(int re i=0;i<=M;++i)coef[now][i]=((i&1)?Cos:Sin)*((i%4<=1)?1:-1)*o/fac[i],o*=a;
break;
}
case 2:{
re double o=1,Exp=exp(b);
for(int re i=0;i<=M;++i)coef[now][i]=Exp*o/fac[i],o*=a;
break;
}
case 3:{
coef[now][1]=a,coef[now][0]=b;
break;
}
}
}
inline void change(int u,int f,double a,double b){
Splay(u);
Set(u,f,a,b);
pushup(u);
}
inline void query(int u,int v,double x){
makeroot(u);
if(findroot(v)!=u){
puts("unreachable");
return;
}
Splay(v);
double res=0;
for(int re i=M;~i;--i){
res*=x;
res+=sum[v][i];
}
printf("%.7f\n",res);
}
signed main(){
fac[0]=1;
for(int re i=1;i<=M;++i)fac[i]=fac[i-1]*i;
n=getint(),m=getint();getint();
for(int re i=1;i<=n;++i){
int f=getint();
double a=getdb(),b=getdb();
Set(i,f,a,b);
}
while(m--){
char op=getop();
int u=getint(),v=getint();
double a,b;
switch(op){
case 'a':link(u+1,v+1);break;
case 'd':cut(u+1,v+1);break;
case 'm':a=getdb(),b=getdb();change(u+1,v,a,b);break;
case 't':a=getdb();query(u+1,v+1,a);break;
}
}
return 0;
}