zoukankan      html  css  js  c++  java
  • 【LOJ】#2289. 「THUWC 2017」在美妙的数学王国中畅游

    题解

    我们发现,题目告诉我们这个东西就是一个lct

    首先,如果只有3,问题就非常简单了,我们算出所有a的总和,所有b的总和就好了

    要是1和2也是多项式就好了……其实可以!也就是下面泰勒展开的用处,我们可以用一个多项式取逼近这个函数,而且,多项式次数越高越准确,我们大概到13次多项式就好了

    如何创造出这个多项式呢,泰勒展开的式子是这样的
    (sum_{i = 0}^{n} frac{f^{(i)}(x_{0}) (x - x_{0})^{i}}{i!})
    其中(f^{(i)}(x))表示(f(x))(i)阶导数

    然后问题就变成了维护13个值的和的lct了

    然后,如何求导
    根据高中选修2-2
    我们有
    (f(g(x)) = g'(x)f'(g(x)))
    对于第一类型的函数
    (sin^{(1)}(ax + b) = acdot cos(ax + b))
    (sin^{(2)}(ax + b) = -a^{2}cdot sin(ax + b))
    (sin^{(3)}(ax + b) = -a^{3}cdot cos(ax + b))
    (sin^{(4)}(ax + b) = a^{4}cdot sin(ax + b))
    4次一个轮回

    对于第二类型的函数
    (f(x)^{(1)} = acdot e^{ax + b})
    (f(x)^{(2)} = a^{2}cdot e^{ax + b})
    (f(x)^{(n)} = a^{n}cdot e^{ax + b})

    = =lct的cut是,先把一个点变成根,另一个点Access一下,再Splay成根,然后断掉根节点的左儿子

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    //#define ivorysi
    #define pb push_back
    #define MAXN 100005
    #define space putchar(' ')
    #define enter putchar('
    ')
    using namespace std;
    typedef long long int64;
    typedef double db;
    int N,M;
    char s[25];
    db fac[20];
    struct Tr {
        Tr *lc,*rc,*fa;
        db sum[14],f[14];
        bool rev;
        void Update() {
    	for(int i = 0 ; i <= 13 ; ++i) sum[i] = f[i];
    	if(lc) for(int i = 0 ; i <= 13 ; ++i) sum[i] += lc->sum[i];
    	if(rc) for(int i = 0 ; i <= 13 ; ++i) sum[i] += rc->sum[i];
        }
        void Reverse() {
    	rev ^= 1;swap(lc,rc);
        }
        void Pushdown() {
    	if(rev) {
    	    if(lc) lc->Reverse();
    	    if(rc) rc->Reverse();
    	    rev = 0;
    	}
        }
    }*tr[MAXN];
    bool which(Tr *u) {
        return u == u->fa->rc;
    }
    bool isRoot(Tr *u) {
        if(!u->fa) return 1;
        return u->fa->rc != u && u->fa->lc != u;
    }
    void Rotate(Tr *u) {
        Tr *v = u->fa,*w = v->fa;
        Tr *b = u == v->lc ? u->rc : u->lc;
        if(!isRoot(v)) (v == w->lc ? w->lc : w->rc) = u;
        u->fa = w;v->fa = u;
        if(b) b->fa = v;
        if(u == v->lc) v->lc = b,u->rc = v;
        else v->rc = b,u->lc = v;
        v->Update();
    }
    void Splay(Tr *u) {
        static Tr* que[MAXN];
        int tot = 0;Tr *x;
        for(x = u ; !isRoot(x) ; x = x->fa) que[++tot] = x;
        que[++tot] = x;
        for(int i = tot ; i >= 1 ; --i) que[i]->Pushdown();
        while(!isRoot(u)) {
    	if(!isRoot(u->fa)) {
    	    if(which(u->fa) == which(u)) Rotate(u->fa);
    	    else Rotate(u);
    	}
    	Rotate(u);
        }
        u->Update();
    }
    void Access(Tr *u) {
        for(Tr *x = NULL ; u ; x = u, u = u->fa) {
    	Splay(u);
    	u->rc = x;
    	u->Update();
        }
    }
    Tr* FindRoot(Tr *u){
        Access(u);Splay(u);
        Tr *res = u;
        res->Pushdown();
        while(res->lc) {res = res->lc;res->Pushdown();}
        return res;
    }
    void MakeRoot(Tr *u) {Access(u);Splay(u);u->Reverse();}
    void Link(Tr *u,Tr *v) {MakeRoot(u);u->fa = v;}
    void Cut(Tr *u,Tr *v) {MakeRoot(u);Access(v);Splay(v);v->lc = u->fa = 0;v->Update();}
    db Select(Tr *u,Tr *v,db x) {
        MakeRoot(u);Access(v);Splay(u);
        db res = 0,t = 1;
        for(int i = 0 ; i <= 13 ; ++i) {
    	res += t * u->sum[i];
    	t *= x;
        }
        return res;
    }
    void Change(Tr *u,int ty,db a,db b) {
        MakeRoot(u);
        memset(u->f,0,sizeof(u->f));
        if(ty == 1) {
    	db x = 1;
    	for(int i = 0 ; i <= 13 ; ++i) {
    	    if(i % 4 == 0) u->f[i] = x * sin(b) / fac[i];
    	    if(i % 4 == 1) u->f[i] = x * cos(b) / fac[i];
    	    if(i % 4 == 2) u->f[i] = -x * sin(b) / fac[i];
    	    if(i % 4 == 3) u->f[i] = -x * cos(b) / fac[i];
    	    x *= a;
    	}
        }
        else if(ty == 2) {
    	db v = exp(b),x = 1;
    	for(int i = 0 ; i <= 13 ; ++i) {u->f[i] = v * x / fac[i];x *= a;}
        }
        else {
    	u->f[1] = a;u->f[0] = b;
        }
        u->Update();
    }
    void Solve() {
        scanf("%d%d",&N,&M);
        scanf("%s",s + 1);
        fac[0] = 1;
        for(int i = 1 ; i <= 13 ; ++i) fac[i] = fac[i - 1] * i;
        int f,u,v;db a,b;
        for(int i = 1 ; i <= N ; ++i) {
    	tr[i] = new Tr;tr[i]->lc = tr[i]->rc = tr[i]->fa = 0;
    	scanf("%d%lf%lf",&f,&a,&b);
    	Change(tr[i],f,a,b);
        }
        for(int i = 1 ; i <= M ; ++i) {
    	scanf("%s",s + 1);
    	if(s[1] == 'a' || s[1] == 'd') {
    	    scanf("%d%d",&u,&v);++u;++v;
    	    if(s[1] == 'a') Link(tr[u],tr[v]);
    	    if(s[1] == 'd') Cut(tr[u],tr[v]);
    	}
    	else if(s[1] == 'm') {
    	    scanf("%d%d%lf%lf",&u,&f,&a,&b);++u;
    	    Change(tr[u],f,a,b);
    	}
    	else {
    	    scanf("%d%d%lf",&u,&v,&a);++u;++v;
    	    if(FindRoot(tr[u]) != FindRoot(tr[v])) puts("unreachable");
    	    else printf("%.8e
    ",Select(tr[u],tr[v],a));
    	}
        }
    }
    
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    firewall详解
    Fiddler使用
    Asp.net Core过滤器
    单例模式
    C# 收银机顾显(客显)及打印小票(58热敏打印机)
    sqlite批量处理数据性能优化
    sqlite 插入数据 too many variables
    winform textbox控件keydown、keypress、keyup简单介绍
    ie兼容placeholder效果
    asp.net mvc全局异常捕获
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9077215.html
Copyright © 2011-2022 走看看