解題:THUWC 2017 在美妙的數學王國中暢遊
題面
_“數字和數學規律主宰著這個世界。”_
在 @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=a\cos(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\n",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 }View Code
解題:THUWC 2017 在美妙的數學王國中暢遊