• [THUWC2017][bzoj5020] 在美妙的数学王国中畅游 [LCT+泰勒展开]


    题面

    LOJ传送门

    思路

    这里很重要

    它提示我们,把给定的三个函数泰勒展开,并用LCT维护每一项泰勒展开式的值,维护十几项就满足了题目的精度要求

    我们考虑一个函数在0位置的泰勒展开

    $f(x)=sum_{i=0}^{infty} frac{x^i f^{(i)}(0)}{i!}$

    发现后面式子里面的$frac{xi}{x!}$可以留到询问时候处理,我们只需要维护$sum_{i=0}{infty} f^{(i)}(0)$即可

    对于$f(x)=sin(ax+b)$,其导函数如下:

    $f{(4n)}(x)=a{4n}sin(ax+b)$

    $f{(4n+1)}(x)=a{4n+1}cos(ax+b)$

    $f{(4n+2)}(x)=-a{4n+2}sin(ax+b)$

    $f{(4n+3)}(x)=-a{4n+3}cos(ax+b)$

    对于$f(x)=e^{ax+b}$,其导函数如下:

    $f{(n)}(x)=a{n}e^{ax+b}$(其实就是乘了一个$a$的幂)

    对于$f(x)=ax+b$,其一阶导数为$f'(x)=a$,没有更高阶导数

    所以,我们在$x=0$的位置泰勒展开这三个函数,并且LCT维护、询问即可

    详见代码

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cassert>
    #include<cmath>
    #define ll long double
    using namespace std;
    inline int read(){
    	int re=0,flag=1;char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-') flag=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    	return re*flag;
    }
    int fa[200010],ch[200010][2],rev[200010];
    long double w[200010][15],sum[200010][15],a[200010],b[200010];int tp[200010];
    //tp={1,2,3} --> {sin,exp,ax+b}
    void calc(int cur){//这里是计算泰勒展开值
            //注意因为我们取的位置是x=0,所以展开以后保存的函数自变量取值为0a+b=b
            ll A=a[cur],B=b[cur],*val=w[cur];register int i;
    	switch(tp[cur]){
    		case 3://sin(ax+b)
    			val[0]=B;val[1]=A;
    			for(i=2;i<12;i++) val[i]=0;
    			break;
    		case 2://exp(ax+b)
    			val[0]=exp(B);
    			for(i=1;i<12;i++) val[i]=val[i-1]*A;
    			break;
    		case 1://ax+b
    			val[0]=sin(B);
    			val[1]=A*cos(B);
    			for(i=2;i<12;i++) val[i]=-val[i-2]*A*A;
    			break;
    		default:assert(0);
    	}
    }
    void update(int cur){
    	for(register int i=0;i<12;i++) sum[cur][i]=sum[ch[cur][0]][i]+sum[ch[cur][1]][i]+w[cur][i];
    }
    void pushrev(int cur){
    	if(!cur) return;
    	swap(ch[cur][0],ch[cur][1]);
    	rev[cur]^=1;
    }
    void pushdown(int cur){
    	if(!rev[cur]) return;
    	pushrev(ch[cur][0]);
    	pushrev(ch[cur][1]);
    	rev[cur]=0;
    }
    bool nroot(int cur){return ch[fa[cur]][0]==cur||ch[fa[cur]][1]==cur;}
    void push(int cur){
    	if(nroot(cur)) push(fa[cur]);
    	pushdown(cur);
    }
    bool get(int cur){return ch[fa[cur]][1]==cur;}
    void rotate(int x){
    	int f=fa[x],ff=fa[f],son=get(x),nr=nroot(f);
    	ch[f][son]=ch[x][son^1];
    	if(ch[f][son]) fa[ch[f][son]]=f;
    	fa[f]=x;ch[x][son^1]=f;
    	fa[x]=ff;
    	if(nr) ch[ff][ch[ff][1]==f]=x;
    	update(f);update(x);
    }
    void splay(int x){
    	push(x);
    	for(int f;nroot(x);rotate(x)){
    		f=fa[x];
    		if(nroot(f)){
    			rotate((get(x)==get(f))?f:x);
    		}
    	}
    }
    void access(int x){
    	for(int y=0;x;y=x,x=fa[x]){
    		splay(x);ch[x][1]=y;update(x);
    	}
    }
    void mroot(int u){
    	access(u);splay(u);pushrev(u);
    }
    void link(int u,int v){
    	mroot(u);fa[u]=v;
    }
    void cut(int u,int v){
    	mroot(u);access(v);splay(v);
    	fa[u]=ch[v][0]=0;update(v);
    }
    int find(int u){
    	access(u);splay(u);
    	while(ch[u][0]) u=ch[u][0];
    	return u;
    }
    long double query(int u,int v,long double x){
    	mroot(u);access(v);splay(v);
    	long double re=0,tmp=1;register int i;
    	for(i=0;i<12;i++){
    		re+=tmp*(long double)(sum[v][i]);
    		tmp/=(long double)(i+1);tmp*=x;
    	}
    	return re;
    }
    int n,m;char s[20];
    int main(){
    	n=read();m=read();scanf("%s",s);int i,t1,t2;double t3,t4;
    	for(i=1;i<=n;i++){
    		fa[i]=ch[i][0]=ch[i][1]=rev[i]=0;
    		tp[i]=read();
    		scanf("%lf%lf",&t3,&t4);
    		a[i]=t3;b[i]=t4;
    		calc(i);
    	}
    	while(m--){//注意题目中点是从0开始的
    		scanf("%s",s);
    		if(s[0]=='a'){
    			t1=read();t2=read();
    			t1++;t2++;
    			link(t1,t2);
    		}
    		if(s[0]=='d'){
    			t1=read();t2=read();
    			t1++;t2++;
    			cut(t1,t2);
    		}
    		if(s[0]=='m'){
    			t1=read();t1++;
    			tp[t1]=read();
    			scanf("%lf%lf",&t3,&t4);
    			a[t1]=t3;b[t1]=t4;
    			mroot(t1);calc(t1);update(t1);
    		}
    		if(s[0]=='t'){
    			t1=read();t2=read();scanf("%lf",&t3);
    			t1++;t2++;
    			if(find(t1)!=find(t2)) puts("unreachable");
    			else printf("%.10lf
    ",(double)(query(t1,t2,t3)));
    		}
    	}
    }
    
  • 相关阅读:
    编写好代码的10条戒律
    [Project] 基开放云平台
    [Project] HUSTOJ随笔
    编码规范:大家都应该做的事情
    ural 1167. Bicolored Horses 夜
    1709. PenguinAvia 夜
    hdu 1011 Starship Troopers 夜
    hdu 2571 命运 夜
    hdu 1561 The more, The Better 夜
    hdu 1598 find the most comfortable road 夜
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/9779314.html
Copyright © 2020-2023  润新知