zoukankan      html  css  js  c++  java
  • THUWC2017 在美妙的数学王国中畅游

    在美妙的数学王国中畅游

    数学王国中,每个人的智商可以用一个属于 ([0,1]) 的实数表示。数学王国中有 (n) 个城市,编号从 (0)(n-1) ,这些城市由若干座魔法桥连接。每个城市的中心都有一个魔法球,每个魔法球中藏有一道数学题。每个人在做完这道数学题之后都会得到一个在 ([0,1]) 区间内的分数。一道题可以用一个从 ([0,1]) 映射到 ([0,1]) 的函数 (f(x)) 表示。若一个人的智商为 (x) ,则他做完这道数学题之后会得到 (f(x)) 分。函数 (f) 有三种形式:

    • 正弦函数 (sin(a x + b) (a in [0,1], b in [0,pi],a+bin[0,pi]))

    • 指数函数 (e^{ax+b} (ain [-1,1], bin [-2,0], a+bin [-2,0]))

    • 一次函数 (ax + b (ain [-1,1],bin[0,1],a+bin [0,1]))

    数学王国中的魔法桥会发生变化,有时会有一座魔法桥消失,有时会有一座魔法桥出现。但在任意时刻,只存在至多一条连接任意两个城市的简单路径(即所有城市形成一个森林)。在初始情况下,数学王国中不存在任何的魔法桥。

    数学王国的国王拉格朗日很乐意传授小R数学知识,但前提是小R要先回答国王的问题。这些问题具有相同的形式,即一个智商为 (x) 的人从城市 (u) 旅行到城市 (v) (即经过 (u)(v) 这条路径上的所有城市,包括 (u)(v) )且做了所有城市内的数学题后,他所有得分的总和是多少。

    【小R教你学数学】

    若函数 (f(x))(n) 阶导数在 ([a,b]) 区间内连续,则对 (f(x))(x_0(x_0in[a,b])) 处使用 (n) 次拉格朗日中值定理可以得到带拉格朗日余项的泰勒展开式

    [f(x)=f(x_0)+frac{f'(x_0)(x-x_0)}{1!}+frac{f''(x_0)(x-x_0)^2}{2!}+ cdots +frac{f^{(n-1)}(x_0)(x-x_0)^{n-1}}{(n-1)!}+frac{f^{(n)}(xi)(x-x_0)^n}{n!},xin[a,b] ]

    其中,当 (x>x_0) 时,(xiin[x_0,x])。当 (x<x_0) 时,(xiin[x,x_0])

    (f^{(n)})表示函数 (f)(n) 阶导数

    【数据范围】

    对于 (100\%) 的数据,(1leq n leq 100000, 1leq m leq 200000)

    题解

    题面里面提示得很清楚了,直接泰勒展开就行了。开始我没看到……

    这题就是考你LCT板子和高中求导公式。

    [sin'(x)=cos(x)\ cos'(x)=-sin(x) ]

    展开式做到16项左右完全没问题。时间复杂度 (O(16 m log n))

    CO int N=100000+10;
    LL fac[16];
    int f[N];LD a[N],b[N];
    int ch[N][2],fa[N],rev[N];
    LD sum[N][16];
    
    IN bool nroot(int x){
    	return ch[fa[x]][0]==x or ch[fa[x]][1]==x;
    }
    IN void push_up(int x){
    	for(int i=0;i<16;++i)
    		sum[x][i]=sum[ch[x][0]][i]+sum[ch[x][1]][i];
    	if(f[x]==1){ // sin
    		LD val=1,sine=sin(b[x]),cosine=cos(b[x]);
    		for(int i=0;i<16;i+=4){
    			sum[x][i]+=val*sine,val*=a[x];
    			sum[x][i+1]+=val*cosine,val*=a[x];
    			sum[x][i+2]-=val*sine,val*=a[x];
    			sum[x][i+3]-=val*cosine,val*=a[x];
    		}
    	}
    	else if(f[x]==2){ // exp
    		LD val=exp(b[x]);
    		for(int i=0;i<16;++i)
    			sum[x][i]+=val,val*=a[x];
    	}
    	else sum[x][0]+=b[x],sum[x][1]+=a[x];
    }
    IN void reverse(int x){
    	swap(ch[x][0],ch[x][1]),rev[x]^=1;
    }
    IN void push_down(int x){
    	if(rev[x]){
    		reverse(ch[x][0]),reverse(ch[x][1]);
    		rev[x]=0;
    	}
    }
    IN void rotate(int x){
    	int y=fa[x],z=fa[y],l=x==ch[y][1],r=l^1;
    	if(nroot(y)) ch[z][y==ch[z][1]]=x;fa[x]=z;
    	ch[y][l]=ch[x][r],fa[ch[x][r]]=y;
    	ch[x][r]=y,fa[y]=x;
    	push_up(y);
    }
    void splay(int x){
    	vector<int> stk(1,x);
    	for(int f=x;nroot(f);) stk.push_back(f=fa[f]);
    	for(;stk.size();stk.pop_back()) push_down(stk.back());
    	for(;nroot(x);rotate(x)){
    		int y=fa[x],z=fa[y];
    		if(nroot(y)) rotate((x==ch[y][1])!=(y==ch[z][1])?x:y);
    	}
    	push_up(x);
    }
    void access(int x){
    	for(int y=0;x;y=x,x=fa[x])
    		splay(x),ch[x][1]=y,push_up(x);
    }
    void make_root(int x){
    	access(x),splay(x),reverse(x);
    }
    int find_root(int x){
    	access(x),splay(x);
    	while(ch[x][0]) x=ch[x][0];
    	return x;
    }
    
    int main(){
    //	freopen("LOJ2289.in","r",stdin),freopen("LOJ2289.out","w",stdout);
    	fac[0]=1;
    	for(int i=1;i<16;++i) fac[i]=fac[i-1]*i;
    	int n=read<int>(),m=read<int>();
    	char type[3];scanf("%s",type);
    	for(int i=1;i<=n;++i){
    		read(f[i]),scanf("%Lf%Lf",a+i,b+i);
    		push_up(i);
    	}
    	while(m--){
    		char opt[10];scanf("%s",opt);
    		if(opt[0]=='a'){
    			int u=read<int>()+1,v=read<int>()+1;
    			make_root(u),fa[u]=v;
    		}
    		else if(opt[0]=='d'){
    			int u=read<int>()+1,v=read<int>()+1;
    			make_root(u),access(u);
    			splay(v),fa[v]=0; // edit 1:splay
    		}
    		else if(opt[0]=='m'){
    			int u=read<int>()+1;
    			read(f[u]),scanf("%Lf%Lf",a+u,b+u);
    			splay(u);
    		}
    		else{
    			int u=read<int>()+1,v=read<int>()+1;
    			LD x;scanf("%Lf",&x);
    			make_root(u);
    			if(find_root(v)!=u){
    				puts("unreachable");
    				continue;
    			}
    			LD val=1,ans=0;
    			for(int i=0;i<16;++i)
    				ans+=sum[v][i]*val/fac[i],val*=x;
    			printf("%.10Le
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    AJAX异步传输——以php文件传输为例
    js控制json生成菜单——自制菜单(一)
    vs2010中关于HTML控件与服务器控件分别和js函数混合使用的问题
    SQL数据库连接到服务器出错——无法连接到XXX
    PHP错误:Namespace declaration statement has to be the very first statement in the script
    【LeetCode】19. Remove Nth Node From End of List
    【LeetCode】14. Longest Common Prefix
    【LeetCode】38. Count and Say
    【LeetCode】242. Valid Anagram
    【LeetCode】387. First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/autoint/p/12069874.html
Copyright © 2011-2022 走看看