题目描述:
雾。
题目分析:
加减抵消了。
其实答案里只有一些前缀的积
s[i]=a[1]∗a[2]∗...∗a[i]
s
[
i
]
=
a
[
1
]
∗
a
[
2
]
∗
.
.
.
∗
a
[
i
]
那么 s[i]对答案的贡献即为
s[i]∗2∗3n−i−1
s
[
i
]
∗
2
∗
3
n
−
i
−
1
由于修改一个数只会对它及后面的前缀积产生影响
那么就是个区间修改,用线段树维护就好了。
预处理逆元
题目链接:
Ac 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
const int mod=1e9+7;
const int maxm=120000;
struct node{
int sum,tag;
}st[maxm<<2];
int a[maxm],pos[maxm],inv[maxm],bin[maxm],s[maxm];
int n,q;
void pushup(int o)
{
st[o].sum=(st[(o<<1)].sum%mod+st[(o<<1)|1].sum%mod)%mod;
}
void col(int o,int v)
{
st[o].sum=(st[o].sum*v)%mod;
st[o].tag=(st[o].tag*v)%mod;
}
void pushdown(int o)
{
if(st[o].tag==1) return;
col((o<<1),st[o].tag);
col((o<<1)|1,st[o].tag);
st[o].tag=1;
}
void build(int o,int l,int r)
{
st[o].tag=1;
if(l>=r)
{
st[o].sum=(l!=n?(s[l]*bin[n-l-1]*2)%mod:s[l]);
return;
}
int mid=(l+r)>>1;
build((o<<1),l,mid),build((o<<1)|1,mid+1,r);
pushup(o);
}
void change(int o,int l,int r,int ql,int qr,int num)
{
if(ql<=l&&r<=qr)
{
col(o,num);
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(ql<=mid) change((o<<1),l,mid,ql,qr,num);
if(qr>mid) change((o<<1)|1,mid+1,r,ql,qr,num);
pushup(o);
}
main()
{
scanf("%lld%lld",&n,&q);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
bin[0]=1;
for(int i=1;i<=n;i++) bin[i]=(bin[i-1]*3)%mod;
inv[1]=1;
for(int i=2;i<=10000;i++)
inv[i]=(mod-mod/i*inv[mod%i]%mod);
s[1]=a[1];
for(int i=2;i<=n;i++) s[i]=(s[i-1]*a[i])%mod;
build(1,1,n);
//printf("%lld\n",st[1].sum);
for(int i=1;i<=q;i++)
{
int pos,y;
scanf("%lld%lld",&pos,&y);
change(1,1,n,pos,n,(y*inv[a[pos]])%mod);
a[pos]=y;
printf("%lld\n",st[1].sum);
}
return 0;
}