_“数字和数学规律主宰着这个世界。”_
在 @i207M 帮助下折腾了半天终于搞懂了导数和泰勒展开,引用某学长在考场上的感受:感觉整个人都泰勒展开了
显然是个奇奇怪怪的东西套上LCT,发现直接维护的话并不能快速链上求和。所以用友好的提示里的泰勒展开,对每个点的函数进行泰勒展开后就变成了维护多项式的和,大概展开十几项精度就够了(我展开了16项)。题目告诉我们了这三个函数在[0,1]都能展开,那就在零点展开呗,这不是最方便的吗=。=
当然因为可能~~并没~~有人和制杖的我一样对导数一无所知~~(初中没学,高中停课了的那种)~~,我还是写的详细一点比较好。
(注意题目中最终带进每个函数的实际是$ax+b$)
先以$sin$为例,下面我们用$d^k(x)$表示关于$x$的函数的$k$阶导数,用$g(x)$表示$ax+b$,用$h(x)$表示题目实际要我们求的东西,我们把$h(x)$在零点展开之后发现是这样的一个东西
$h(x)=h(0)+frac{d^1(0)(x-0)}{1!}+frac{d^2(0)(x-0)^2}{2!}+......$
所以说选零点展开多方便=。=
$h(x)=h(0)+(d^1(0)/1!)x+(d^2(0)/2!)x^2+......$
好,现在把$h$换回去,那$h(0)$实际是$f(g(0))=sin(a*0+b)=sin(b)$,那导数$d(0)$呢?我们经过各种途径可以知道$sin x$求导是$cos x$,$cos x$求导是$-sin x$,当然还有$ax+b$求导是$a$,现在问题是$h$是两个函数套起来,所以你还需要知道
链式法则:设函数$h(x)=f(g(x))$,那么函数$h$在$x$处的导数$h'(x)=f'(g(x))g'(x)$,即$f$在$g(x)$处求导的结果乘上$g$在$x$处求导的结果
应用一下:$h'(0)=f'(g(0))g'(0)=cos(g(0))a=acos(b)$
更高阶的导数仍然应用链式法则求,注意符号和$sin/cos$,然后就是高一阶多乘一个$a$
于是我们可以得出另外两种函数套着$g(x)=ax+b$时的导数
$f(x)=e^x$求导还是$e^x$,所以$f(x)=e^x->h'(x)=f'(g(0))g'(0)=e^{g(0)}a=a*e^b$,然后再每高一阶就多乘一个$a$
$f(x)=x$求导是$1$,所以$f(x)=x->h'(x)=f'(g(0))g'(0)=a$,更高阶的导数都是零
然后是注意精度,每次修改先预处理一下$sin,cos$和$e$,不然精度会爆炸
最重要的是,LCT先不要写错=。=
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const double inf=1e9; 7 const int N=100005,K=20; 8 double exa[N][K],ply[N][K],fac[N]; 9 int siz[N],fth[N],son[N][2],rev[N],stk[N]; 10 double t2,t3; int n,m,t1,t4,top; char rd[20]; 11 void Prework() 12 { 13 fac[0]=1; 14 for(int i=1;i<=16;i++) 15 fac[i]=fac[i-1]*i; 16 } 17 double Calc(int nde,double var) 18 { 19 double ret=0,npw=1; 20 for(int i=0;i<=15;i++) 21 ret+=ply[nde][i]*npw,npw*=var;//,printf("%lf ",ply[nde][i]);puts(""); 22 return ret; 23 } 24 void Pushup(int nde) 25 { 26 int lson=son[nde][0],rson=son[nde][1]; 27 for(int i=0;i<=15;i++) 28 ply[nde][i]=exa[nde][i]+ply[lson][i]+ply[rson][i]; 29 } 30 void Release(int nde) 31 { 32 if(rev[nde]) 33 { 34 int &lson=son[nde][0],&rson=son[nde][1]; 35 rev[nde]^=1,rev[lson]^=1,rev[rson]^=1; 36 swap(lson,rson); 37 } 38 } 39 bool Nottop(int nde) 40 { 41 int fa=fth[nde]; 42 return nde==son[fa][0]||nde==son[fa][1]; 43 } 44 void Rotate(int nde) 45 { 46 int fa=fth[nde],gr=fth[fa],isl=nde==son[fa][0]; 47 if(Nottop(fa)) son[gr][fa==son[gr][1]]=nde; 48 fth[nde]=gr,fth[fa]=nde,fth[son[nde][isl]]=fa; 49 son[fa][isl^1]=son[nde][isl],son[nde][isl]=fa; 50 Pushup(fa),Pushup(nde); 51 } 52 void Splay(int nde) 53 { 54 stk[top=1]=nde; 55 for(int i=nde;Nottop(i);i=fth[i]) 56 stk[++top]=fth[i]; 57 while(top) Release(stk[top--]); 58 while(Nottop(nde)) 59 { 60 int fa=fth[nde],gr=fth[fa]; 61 if(Nottop(fa)) 62 Rotate(((son[fa][0]==nde)==(son[gr][0]==fa))?fa:nde); 63 Rotate(nde); 64 } 65 Pushup(nde); 66 } 67 void Access(int nde) 68 { 69 int mem=nde,lst=0; 70 while(nde) 71 { 72 Splay(nde),son[nde][1]=lst; 73 Pushup(nde),lst=nde,nde=fth[nde]; 74 } 75 Splay(mem); 76 } 77 void Turnroot(int nde) 78 { 79 Access(nde),rev[nde]^=1; 80 } 81 void Split(int x,int y) 82 { 83 Turnroot(x),Access(y); 84 } 85 int Getroot(int nde) 86 { 87 Access(nde); 88 while(son[nde][0]) 89 nde=son[nde][0]; 90 Splay(nde); 91 return nde; 92 } 93 void Link(int x,int y) 94 { 95 Turnroot(x),fth[x]=y; 96 } 97 void Cut(int x,int y) 98 { 99 Split(x,y),fth[x]=son[y][0]=0,Pushup(y); 100 } 101 void Setfunc(int x,int t,double a,double b)//h(x)=f(g(x)),g(x)=ax+b 102 { 103 memset(exa[x],0,sizeof exa[x]); 104 if(t==1) 105 { 106 double o=1,Sin=sin(b),Cos=cos(b);//f(x)=sin(x) 107 for(int i=0;i<=15;i++)//h'(x)=f'(g(x))g'(x)=cos(x),h''(x)=-sin(x) 108 exa[x][i]=((i%2==1)?Cos:Sin)*((i%4<=1)?1:-1)*o/fac[i],o*=a; 109 } 110 if(t==2) 111 { 112 double o=1,Exp=exp(b);//f(x)=e^x 113 for(int i=0;i<=15;i++)//h'(x)=f'(g(x))g'(x)=e^b*a 114 exa[x][i]=Exp*o/fac[i],o*=a; 115 } 116 if(t==3)//f(x)=x 117 exa[x][0]=b,exa[x][1]=a;//h'(x)=f'(g(x))g'(x)=1*a=a 118 } 119 void Change(int x,int t,double a,double b) 120 { 121 Splay(x),Setfunc(x,t,a,b),Pushup(x); 122 } 123 double Query(int x,int y,double a) 124 { 125 Turnroot(x); 126 if(Getroot(y)==x) 127 { 128 Splay(y); 129 return Calc(y,a); 130 } 131 else return -inf; 132 } 133 int main() 134 { 135 Prework(); 136 scanf("%d%d%s",&n,&m,rd); 137 for(int i=1;i<=n;i++) 138 scanf("%d%lf%lf",&t1,&t2,&t3),Setfunc(i,t1,t2,t3); 139 while(m--) 140 { 141 scanf("%s",rd); 142 if(rd[0]=='a') scanf("%d%d",&t1,&t4),Link(t1+1,t4+1); 143 else if(rd[0]=='d') scanf("%d%d",&t1,&t4),Cut(t1+1,t4+1); 144 else if(rd[0]=='m') scanf("%d%d%lf%lf",&t1,&t4,&t2,&t3),Change(t1+1,t4,t2,t3); 145 else if(rd[0]=='t') 146 { 147 scanf("%d%d%lf",&t1,&t4,&t2); 148 double qry=Query(t1+1,t4+1,t2); 149 if(qry<=-inf) puts("unreachable"); 150 else printf("%.7f ",qry); 151 } 152 // for(int i=1;i<=3;i++,puts("")) 153 // for(int j=0;j<=10;j++) printf("%lf ",ply[i][j]); 154 } 155 return 0; 156 }