大佬教我做题
ans=∏i=LR(1−pi)=eln∏Ri=L(1−pi)=e∑Ri=Lln(1−pi)
a
n
s
=
∏
i
=
L
R
(
1
−
p
i
)
=
e
ln
∏
i
=
L
R
(
1
−
p
i
)
=
e
∑
i
=
L
R
ln
(
1
−
p
i
)
将 ln(1−x) ln ( 1 − x ) 泰勒展开
ln(1−x)=−∑i=1∞xii
ln
(
1
−
x
)
=
−
∑
i
=
1
∞
x
i
i
用线段树维护 x x 的前 次幂就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N=100010;
const int M=99;
const db Eps=1e-7;
int k,n,m,x,y;
db t;
db a[N],c[N<<2][M],p[N<<2];
void Up(int x) {
for(int i=1;i<M;i++) c[x][i]=c[x<<1][i]+c[x<<1|1][i];
}
void Update_node(int x,db y) {
db t=1;
for(int i=1;i<M;i++) t*=y,c[x][i]*=t;
p[x]*=y;
}
void Down(int x) {
if(p[x]==1) return;
Update_node(x<<1,p[x]);Update_node(x<<1|1,p[x]);
p[x]=1;
}
void Build(int x,int l,int r) {
p[x]=1;
if(l==r) {
c[x][1]=a[l];
for(int i=2;i<M;i++) c[x][i]=c[x][i-1]*a[l];
return;
}
int Mid=l+r>>1;
Build(x<<1,l,Mid);Build(x<<1|1,Mid+1,r);
Up(x);
}
void Update(int x,int l,int r,int L,int R,db y) {
if(l>R||r<L) return;
if(l>=L&&r<=R) {
Update_node(x,y);
return;
}
Down(x);
int Mid=l+r>>1;
Update(x<<1,l,Mid,L,R,y);Update(x<<1|1,Mid+1,r,L,R,y);
Up(x);
}
db Query(int x,int l,int r,int L,int R) {
if(l>R||r<L) return 0;
if(l>=L&&r<=R) {
db Ans=0;
for(int i=1;i<M;i++) Ans-=c[x][i]/i;
return Ans;
}
Down(x);
int Mid=l+r>>1;
return Query(x<<1,l,Mid,L,R)+Query(x<<1|1,Mid+1,r,L,R);
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
Build(1,1,n);
while(m--) {
scanf("%d%d%d",&k,&x,&y);
if(!k) printf("%.7lf\n",exp(Query(1,1,n,x,y)));else scanf("%lf",&t),Update(1,1,n,x,y,t);
}
return 0;
}