解题: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=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 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10292179.html