zoukankan      html  css  js  c++  java
  • [BZOJ5020][THUWC 2017]在美妙的数学王国中畅游

    数学王国里有n座城市,每座城市有三个参数(f)(a)(b),一个智商为(x)的人经过一座城市的获益(f(x))
    (f=1),则(f(x)=sin(ax+b))
    (f=2),则(f(x)=e^{ax+b})
    (f=3),则(f(x)=ax+b)
    会发生如下四种事件:
    1、有两个城市之间新建了道路;
    2、有两个城市之间的道路被摧毁了;
    3、城市i的三个参数被修改了;
    4、求智商为x的人从u走到v的获益总和。
    保证任何时候图是一个森林。

    题解

    这是一道数学题

    如果每座城市的(f)都是(3)你会做吗?
    很简单,LCT维护一下路径上的(sum a,sum b)即可。
    可见我们维护出来的就是函数的一次项系数和常系数。
    所以说,如果我告诉你每座城市都是一个不超过13项的多项式函数,你应该不会还不知道怎么做了吧。
    但显然这(sin(ax+b))啊,什么(e^{ax+b})啊,这都是些什么鬼。
    但如果我可以把它们展开成多项式呢?
    根据泰勒公式,我们有

    [f(x)=sum_{i=0}^{n} frac{f^{(i)}(x_0)*(x-x_0)^i}{i!} ]

    其中(f^{(i)}(x))表示函数(f(x))(i)阶导。
    上式是一个近似式,近似度随(n)的取值而不断递增。要精确到题目要求的1e-7的话(n)只要取12,13就可以了。

    数学小课堂——关于指数函数、三角函数、复活(雾)函数的求导

    指数函数的求导

    [(a^x)'=a^x*ln a ]

    ((ln a)代表取自然对数)。
    特殊的,

    [(e^x)'=e^x ]

    三角函数的求导

    [(sin x)'=cos x ]

    [(cos x)'=-sin x ]

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

    [(-cos x)'=sin x ]

    (所以说是循环四个,周期!)
    复合函数

    [[f(g(x))]'=g'(x)*f'(g(x)) ]

    放到这道题里面去

    [sin'(ax+b)=acos(ax+b) ]

    [sin''(ax+b)=-a^2sin(ax+b) ]

    [sin'''(ax+b)=-a^3cos(ax+b) ]

    以此类推

    [(e^{ax+b})^{(n)}=a^ne^{ax+b} ]

    一次函数就不说了
    然后这题就做完了

    code

    upt 18-08-07 : 更新了一份代码,现在(BZ)能过了虽然是在最后一版

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int N = 100005;
    const int M = 16;
    int n,m,fa[N],ch[2][N],rev[N],f[N],Stack[N],top;
    double jc[M],sum[M][N],a[N],b[N];
    char type[N],s[N];
    bool son(int x){
    	return ch[1][fa[x]]==x;
    }
    bool isroot(int x){
    	return ch[0][fa[x]]!=x&&ch[1][fa[x]]!=x;
    }
    void reverse(int x){
    	if (!x) return;
    	swap(ch[0][x],ch[1][x]);rev[x]^=1;
    }
    void pushup(int x){
        for (int i=0;i<M;++i)
            sum[i][x]=sum[i][ch[0][x]]+sum[i][ch[1][x]];
        if (f[x]==1){
            double val=1,Sin=sin(b[x]),Cos=cos(b[x]);
            for (int i=0;i<M;i+=4){
                sum[i][x]+=Sin*val;val*=a[x];
    			sum[i+1][x]+=Cos*val;val*=a[x];
    			sum[i+2][x]-=Sin*val;val*=a[x];
    			sum[i+3][x]-=Cos*val;val*=a[x];
            }
        }
        if (f[x]==2){
            double val=exp(b[x]);sum[0][x]+=val;
            for (int i=1;i<M;++i)
                val*=a[x],sum[i][x]+=val;
        }
        if (f[x]==3)
            sum[0][x]+=b[x],sum[1][x]+=a[x];
    }
    void pushdown(int x){
    	if (!rev[x]) return;
    	reverse(ch[0][x]);reverse(ch[1][x]);rev[x]=0;
    }
    void rotate(int x){
    	int y=fa[x],z=fa[y],c=son(x);
    	ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    	fa[x]=z;if (!isroot(y)) ch[son(y)][z]=x;
    	ch[c^1][x]=y;fa[y]=x;pushup(y);
    }
    void splay(int x){
        Stack[++top]=x;
        for (int i=x;!isroot(i);i=fa[i])
            Stack[++top]=fa[i];
        while (top) pushdown(Stack[top--]);
        for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
    		if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
        pushup(x);
    }
    void access(int x){
    	for (int y=0;x;y=x,x=fa[x])
    		splay(x),ch[1][x]=y,pushup(x);
    }
    void makeroot(int x){
    	access(x);splay(x);reverse(x);
    }
    int findroot(int x){
    	access(x);splay(x);
    	while(ch[0][x])x=ch[0][x];
    	splay(x);return x;
    }
    void split(int x,int y){
    	makeroot(x);access(y);splay(y);
    }
    void link(int x,int y){
    	makeroot(x);fa[x]=y;
    }
    void cut(int x,int y){
    	split(x,y);ch[0][y]=fa[x]=0;
    }
    int main(){
    //  freopen("math.in","r",stdin);
    //	freopen("math.out","w",stdout);
        jc[0]=1;
        for (int i=1;i<M;++i)
            jc[i]=jc[i-1]*i;
        scanf("%d %d %s",&n,&m,type);
        for (int i=1;i<=n;++i)
            scanf("%d %lf %lf",&f[i],&a[i],&b[i]);
        while (m--){
            int u,v,ff;
            double aa,bb,x,IQ,ans;
            scanf("%s",s);
            if (s[0]=='a'){
                scanf("%d %d",&u,&v);
                ++u;++v;link(u,v);
            }
            if (s[0]=='d'){
                scanf("%d %d",&u,&v);
                ++u;++v;cut(u,v);
            }
            if (s[0]=='m'){
                scanf("%d %d %lf %lf",&u,&ff,&aa,&bb);
                ++u;makeroot(u);
                f[u]=ff;a[u]=aa;b[u]=bb;
                pushup(u);
            }
            if (s[0]=='t'){
                scanf("%d %d %lf",&u,&v,&IQ);x=1;
                ++u;++v;
                if (findroot(u)^findroot(v)) {puts("unreachable");continue;}
                split(u,v);
                ans=0;
                for (int i=0;i<M;++i)
    				ans+=sum[i][v]*x/jc[i],x*=IQ;
                printf("%.8e
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    构建之法阅读笔记07
    7-第一阶段SCRUM冲刺
    第一阶段个人冲刺博客第十天
    第一阶段个人冲刺博客第九天
    第九周学习进度博客
    java项目(学习和研究)
    让计算机干活
    os基础
    树和图的一些算法
    java代码理解
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8148732.html
Copyright © 2011-2022 走看看