zoukankan      html  css  js  c++  java
  • 「LOJ 2289」「THUWC 2017」在美妙的数学王国中畅游——LCT&泰勒展开

    题目大意:

      传送门

      给一个动态树,每个节点上维护一个函数为$f(x)=sin(ax+b)$、$f(x)=e^{ax+b}$、$f(x)=ax+b$中的一个。

      支持删边连边,修改节点上函数的操作。

      每次询问$u$到$v$路径上所有函数带入$x$值的和。

    题解:

      给了个泰勒公式

      (粘贴自百度)

      不过……要是会导数这题也应该知道……不会导数给了也是白给……不知道出题人怎么想的……

      话说直接给麦克劳林展开+导数不好吗……

      因为$f(x)=e^x$的导数$f'(x)=e^x$所有当取$x_0=0$时就有其麦克劳林展开:

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

      而$sin(x)$导数为$cos(x)$,$cos(x)$导数为$-sin(x)$。所以当$x_0=0$时发现$f(x)$奇数$i$阶导数为$(-1)^{frac{i-1}{2}}$,偶数阶导均为0。有其麦克劳林展开:

      $f(x)=sum_{i=0}^{infty} (-1)^i frac{ x^{2i+i} }{(2i+i)!}$

      考虑这题数据范围不需要展开太多,大概20项就够了。

      然后把给的参数$ax+b$带进去得到一个关于$x$的长度为20的多项式,我们LCT的时候维护链上系数和即可。

    代码:

    #include "bits/stdc++.h"
    
    inline int read (){
        int s=0,k=1;char ch=getchar();
        while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar();
        while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar();
        return s*k;
    }
    
    #define double long double
    
    using namespace std;
    
    const int N=1e5+10;
    
    int C[20][20];
    long long fac[20];
    
    inline void init() {
        register int i,j;
        for (C[0][0]=i=1;i<20;++i)
            for (C[i][0]=j=1;j<=i;++j)
                C[i][j]=C[i-1][j]+C[i-1][j-1];
        for (fac[0]=i=1;i<20;++i)
            fac[i]=fac[i-1]*i;
    }
    
    namespace LCT {
        #define rev(t) (t?t->rev^=1:0)
        #define is_root(t) (!t->fa||(t->fa->son[0]!=t&&t->fa->son[1]!=t))
        #define son(t) (t->fa->son[1]==t)
        #define size(t,s) (t?t->size[s]:0)
        struct node {
            node () {fa=son[0]=son[1]=NULL,rev=0,memset(self,0,sizeof self),memset(size,0,sizeof size);}
            node *fa,*son[2];
            double self[20],size[20];
            int rev;
            inline void pushdown()  {
                if (!rev) return ;
                swap(son[0],son[1]);
                rev(son[0]),rev(son[1]);
                rev=0;
            }
            inline void update() {
                for (int i=0;i<20;++i)
                    size[i]=size(son[0],i)+size(son[1],i)+self[i];
            }
            inline double ans(double x) {
                double ans=0,now=1.0;
                for (int i=0;i<20;++i,now*=x)
                    ans+=now*size[i];
                return ans;
            }
            inline void calc(int type,double a[],double b[]) {
                memset(self,0,sizeof self);
                if (type==1) {
    
                    for (int i=0;i<20;++i)  if (i%2)
                        for (int j=0;j<=i;++j) {
                            self[j]+=((((i-1)/2)&1)?-1:1)*a[j]*b[i-j]*C[i][j]/fac[i];     
                        }           
                }else if(type==2) {
                    for (int i=0;i<20;++i)
                        for (int j=0;j<=i;++j)
                            self[j]+=a[j]*b[i-j]*C[i][j]/fac[i];
                }else self[0]=b[1],self[1]=a[1];
            }
    
        }tree[N],*tmp[N];
        
        inline void rotate(node *p){
            int a=son(p)^1;node *f=p->fa;
            f->son[a^1]=p->son[a];
            if (p->son[a]) p->son[a]->fa=f;
            p->fa=f->fa;
            if (!is_root(f)) f->fa->son[son(f)]=p;
            f->fa=p,p->son[a]=f,f->update(),p->update();
        }
        
        inline void update(node *p){
            if (!is_root(p)) update(p->fa);
            p->pushdown();
        }
        
        inline void splay(node *p){
            register int pos=0;
            for(node *t=p;;t=t->fa){
                tmp[++pos]=t;
                if(is_root(t)) break;
            }
            for(;pos;--pos) tmp[pos]->pushdown();
            for(;!is_root(p);rotate(p))
                if(!is_root(p->fa)) rotate(son(p)==son(p->fa)?p->fa:p);
        }
        
        inline void access(node *p){
            for(node *pre=NULL;p;pre=p,p=p->fa)
                splay(p),p->son[1]=pre,p->update();
        }
        
        inline void make_root(node *x) {
            access(x),splay(x),x->rev^=1;
        }
        
        inline void link(node *x,node *y) {
            make_root(x);access(y),splay(y),x->fa=y;
            y->update();
        }
        
        inline void cut(node *x,node *y){
            make_root(x),access(y),splay(y);
            x->fa=y->son[0]=NULL;y->update();
        }
        
        inline double query(node *x,node *y,double xx){
            make_root(x),access(y),splay(y);
            return y->ans(xx);
        }
        
        inline int finds(node *x) {
            access(x),splay(x);
            while (x->son[0]) x=x->son[0],x->pushdown();
            return x-tree;
        }
    }
    
    int n,m;
    double a[20],b[20];
    
    int main (int argc, char const* argv[]){
        //freopen("2289.in","r",stdin);
        init();    
        char opt[20];
        n=read(),m=read(),scanf("%s",opt);
        int type;
        a[0]=b[0]=1.0;
        using namespace LCT;
        for (int i=1;i<=n;++i)  {
            type=read();
            scanf("%Lf%Lf",a+1,b+1);
            for (int j=2;j<20;++j)
                a[j]=a[j-1]*a[1],
                b[j]=b[j-1]*b[1];
            tree[i].calc(type,a,b);   
        }
    
        int u,v,c;
        double x;
        while (m--) {
            scanf("%s",opt);
            if (opt[0]=='a') {
                u=read()+1,v=read()+1;
                link(&tree[u],&tree[v]);
            }else if (opt[0]=='d') {
                u=read()+1,v=read()+1;
                cut(&tree[u],&tree[v]);
            }
            else if (opt[0]=='m') {
                c=read()+1,type=read();
                scanf("%Lf%Lf",a+1,b+1);
                for (int j=2;j<20;++j)
                    a[j]=a[j-1]*a[1],
                    b[j]=b[j-1]*b[1];
                make_root(&tree[c]);
                tree[c].calc(type,a,b);
                tree[c].update();
            }
            else {
                u=read()+1,v=read()+1;
                scanf("%Lf",&x);
                if (finds(&tree[u])^finds(&tree[v]))   {
                    puts("unreachable");
                }
                else {
                    printf("%.8Le
    ",query(&tree[u],&tree[v],x));
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    iOS如何测试微信小游戏&小程序?
    Android如何测试微信小游戏&小程序?
    Perfdog玩转内存泄漏
    【版本更新】PerfDog 4.0来袭,新增图表操作提示、子进程帧率精准测试,优化诸多细节
    PerfDog常用小技巧
    FAQ | PerfDog常见问题解答第一期
    扒一扒安卓渲染原理
    PerfDog测试腾讯视频、优酷、爱奇艺视频类小程序性能
    PerfDog可以助力高帧率游戏生态更全面发展
    【版本更新】PerfDog中文版震撼来袭,Web平台支持手机版与所有主流浏览器
  • 原文地址:https://www.cnblogs.com/Troywar/p/8982707.html
Copyright © 2011-2022 走看看