泰勒展开

一般取x0=0时即可用多项式拟合某函数

CODECHEF APRIL18 CHEFAT

所以

线段树维护多项式。由于x<0.9,可以取较小的n得到较好的拟合效果

#include <cstdio>
#include <iostream>
#include <cmath>
#define LDB double
using namespace std;

  const int lim=120;
  int cnt,n,q;
  LDB p[200001];

  struct treenode{
      int l,r,lc,rc;
      LDB toadd,poly[lim+10];
      
      void taylor(LDB num){
        LDB p=1;
      for (int i=1;i<=lim;i++){
          p*=num;
          poly[i]=-p/i;
      }
    }
  }tr[200001];

  void pushdown(int po){
      if (fabs(tr[po].toadd-1)>1e-9){
        LDB p=1;
      for (int i=1;i<=lim;i++){
          p*=tr[po].toadd;
          tr[po].poly[i]*=p;
      }    
      tr[tr[po].lc].toadd*=tr[po].toadd;
      tr[tr[po].rc].toadd*=tr[po].toadd;
      tr[po].toadd=1;
    }
  }

  void update(int po){
      pushdown(po);
      LDB p1=1,p2=1;
      for (int i=1;i<=lim;i++){
        p1*=tr[tr[po].lc].toadd;p2*=tr[tr[po].rc].toadd;
        tr[po].poly[i]=tr[tr[po].lc].poly[i]*p1+tr[tr[po].rc].poly[i]*p2;    
    }
  }

  void build(int l,int r){
      tr[++cnt].l=l;tr[cnt].r=r;tr[cnt].toadd=1;
      if (l==r){
        tr[cnt].taylor(p[l]);
      return;    
    }
    
    int mid=(l+r)>>1,t=cnt;
    tr[t].lc=cnt+1;build(l,mid);
    tr[t].rc=cnt+1;build(mid+1,r);
    update(t);
  }

  LDB que(int po,int l,int r){
      pushdown(po);
      if (tr[po].l==l&&tr[po].r==r){
        LDB ret=0;
      for (int i=1;i<=lim;i++) ret+=tr[po].poly[i];
      return(ret);    
    }
    
    LDB ret=0;
    int mid=(tr[po].l+tr[po].r)>>1;
    if (l<=mid) ret+=que(tr[po].lc,l,min(mid,r));
    if (r>mid)  ret+=que(tr[po].rc,max(mid+1,l),r);
    return(ret);
  }
  
  void edi(int po,int l,int r,LDB num){
      pushdown(po);
      if (tr[po].l==l&&tr[po].r==r){
        tr[po].toadd*=num;return;    
    }
    
    int mid=(tr[po].l+tr[po].r)>>1;
    if (l<=mid) edi(tr[po].lc,l,min(mid,r),num);
    if (r>mid)  edi(tr[po].rc,max(mid+1,l),r,num);
    update(po); 
  }

  int main(){
      scanf("%d%d",&n,&q);
      for (int i=1;i<=n;i++) scanf("%lf",&p[i]);
      build(1,n);
      
      for (int i=1;i<=q;i++){
        int opt,t1,t2;LDB t3;
        scanf("%d%d%d",&opt,&t1,&t2);
      if (opt==0){
          LDB t=que(1,t1,t2);
          printf("%.9lf\n",exp(t));
      }else{
        scanf("%lf",&t3);
        edi(1,t1,t2,t3);
      }
    }
  }

 

posted @ 2018-04-17 19:44  z1j1n1  阅读(340)  评论(0编辑  收藏  举报