• [LOJ2289][THUWC2017]在美妙的数学王国中畅游:Link-Cut Tree+泰勒展开


    分析

    又有毒瘤出题人把数学题出在树上了。

    根据泰勒展开,有:

    [e^x=1+frac{1}{1!}x+frac{1}{2!}x^2+frac{1}{3!}x^3+... ]

    [sin(x)=x-frac{1}{3!}x^3+frac{1}{5!}x^5-... ]

    然而题目里(x)的位置是一个(ax+b)怎么办啊?直接根据二项式定理暴力展开就好了。

    题目中要求支持加边删边,可以想到肯定是LCT。维护一下链上所有结点各次项系数和,查询时直接利用整条链的信息计算答案即可。

    计算到(16)次项精度就没啥问题了。(其实是为了凑个整)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=100005;
    const int MAXM=200005;
    int n,m,top,sta[MAXN];
    char opt[15];
    double fac[20],c[20][20],powk[20],powb[20];
    struct lct{
    	int fa,ch[2];
    	int opt;
    	double k,b;
    	double v[20];
    	double sum[20];
    	bool tag;
    }a[MAXN];
    
    inline void pre_process(){
    	fac[0]=1;
    	rin(i,1,16) fac[i]=fac[i-1]*i;
    	c[0][0]=1;
    	rin(i,1,16) rin(j,0,i){
    		c[i][j]=c[i-1][j];
    		if(j) c[i][j]+=c[i-1][j-1];
    	}
    }
    
    #define lc a[x].ch[0]
    #define rc a[x].ch[1]
    inline bool isroot(int x){
    	return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
    }
    
    inline void pushup(int x){
    	rin(i,0,16) a[x].sum[i]=a[x].v[i]+a[lc].sum[i]+a[rc].sum[i];
    }
    
    inline void pushr(int x){
    	std::swap(lc,rc);
    	a[x].tag^=1;
    }
    
    inline void pushdown(int x){
    	if(!a[x].tag) return;
    	if(lc) pushr(lc);
    	if(rc) pushr(rc);
    	a[x].tag=0;
    }
    
    inline void info(int x){
    	memset(a[x].v,0,sizeof a[x].v);
    	if(a[x].opt==1){
    		powk[0]=powb[0]=1;
    		rin(i,1,16){
    			powk[i]=powk[i-1]*a[x].k;
    			powb[i]=powb[i-1]*a[x].b;
    		}
    		int pn=1;
    		for(int i=1;i<=16;i+=2){
    			rin(j,0,i){
    				a[x].v[j]+=pn*powk[j]*powb[i-j]*c[i][j]/fac[i];
    			}
    			pn=-pn;
    		}
    	}
    	else if(a[x].opt==2){
    		powk[0]=powb[0]=1;
    		rin(i,1,16){
    			powk[i]=powk[i-1]*a[x].k;
    			powb[i]=powb[i-1]*a[x].b;
    		}
    		rin(i,0,16){
    			rin(j,0,i){
    				a[x].v[j]+=powk[j]*powb[i-j]*c[i][j]/fac[i];
    			}
    		}
    	}
    	else{
    		a[x].v[1]=a[x].k;
    		a[x].v[0]=a[x].b;
    	}
    	pushup(x);
    }
    
    inline void rotate(int x){
    	int y=a[x].fa,z=a[y].fa,f=(a[y].ch[1]==x),g=a[x].ch[f^1];
    	if(!isroot(y)) a[z].ch[a[z].ch[1]==y]=x;
    	a[x].ch[f^1]=y;
    	a[y].ch[f]=g;
    	if(g) a[g].fa=y;
    	a[y].fa=x;
    	a[x].fa=z;
    	pushup(y);
    }
    
    inline void splay(int x){
    	int y=x,z=0;
    	top=1,sta[1]=y;
    	while(!isroot(y)) sta[++top]=y=a[y].fa;
    	while(top) pushdown(sta[top--]);
    	while(!isroot(x)){
    		y=a[x].fa,z=a[y].fa;
    		if(!isroot(y)){
    			if((a[y].ch[0]==x)==(a[z].ch[0]==y)) rotate(y);
    			else rotate(x);
    		}
    		rotate(x);
    	}
    	pushup(x);
    }
    
    inline void access(int x){
    	for(int y=0;x;x=a[y=x].fa){
    		splay(x);
    		rc=y;
    		pushup(x);
    	}
    }
    
    inline void makeroot(int x){
    	access(x);
    	splay(x);
    	pushr(x);
    }
    
    inline int findroot(int x){
    	access(x);
    	splay(x);
    	while(lc) x=lc;
    	return x;
    }
    
    inline void split(int x,int y){
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    
    inline void link(int x,int y){
    	makeroot(x);
    	a[x].fa=y;
    }
    
    inline void cut(int x,int y){
    	split(x,y);
    	a[x].fa=0;
    	a[y].ch[0]=0;
    	pushup(y);
    }
    
    inline double query(int x,int y,double iq){
    	split(x,y);
    	double tt=1,ret=0;
    	rin(i,0,16){
    		ret+=a[y].sum[i]*tt;
    		tt*=iq;
    	}
    	return ret;
    }
    #undef lc
    #undef rc
    
    int main(){
    	pre_process();
    	n=read(),m=read();
    	scanf("%s",opt+1);
    	rin(i,1,n){
    		a[i].opt=read();
    		scanf("%lf%lf",&a[i].k,&a[i].b);
    		info(i);
    	}
    	while(m--){
    		scanf("%s",opt+1);
    		if(opt[1]=='a'){
    			int x=read()+1,y=read()+1;
    			link(x,y);
    		}
    		else if(opt[1]=='d'){
    			int x=read()+1,y=read()+1;
    			cut(x,y);
    		}
    		else if(opt[1]=='m'){
    			int x=read()+1;a[x].opt=read();
    			scanf("%lf%lf",&a[x].k,&a[x].b);
    			getchar();
    			splay(x);
    			info(x);
    		}
    		else{
    			int x=read()+1,y=read()+1;
    			double iq;scanf("%lf",&iq);
    			getchar();
    			if(findroot(x)!=findroot(y)){
    				printf("unreachable
    ");
    				continue;
    			}
    			printf("%.8le
    ",query(x,y,iq));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    开始学习
    C# Excel批注“哪种开发语言最好”
    [LeetCode] Longest Substring Without Repeating Characters
    (Android 即时通讯) [悬赏],不管是谁发现一个漏洞奖励人民币1000元!
    10进制转16进制
    【2】按照Django官网,创建一个web app 创建app/创建相应的数据库表
    HTML5新特性之WebSocket
    Drupal 7模板(主题钩子)的建议
    检測磁盘驱动的健康程度SMART
    BZOJ2527: [Poi2011]Meteors
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10182946.html
Copyright © 2020-2023  润新知