您的位置:首页 > 其它

BZOJ4597 [Shoi2016]随机序列

2016-05-18 16:04 387 查看
发现对于除了全是乘法之外的任意一个序列,有一个与之一一对应的序列,两个序列相加后除了第一项全部抵消,所以只有前缀积被记入答案,第n个元素的前缀积被计算了一次,对于1<=i<n,到第i个元素的前缀积被计算了2*3^(n-i-1)次,答案即为sigma 第i个前缀积被计算的次数*第i个前缀积

更改一个数相当于对他和他后面的所有前缀积乘上这个数的逆元再乘上新数

线段树维护即可

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 100010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
int n,m;
ll a[MAXN];
ll s[MAXN];
ll v[MAXN*4],ch[MAXN*4];
ll tim[MAXN];
ll mi(ll x,ll y){
ll re=1;
while(y){
if(y&1){
re=re*x%MOD;
}
x=x*x%MOD;
y>>=1;
}
return re;
}
ll ni(ll x){
return mi(x,MOD-2);
}
inline void toch(int x,ll y){
v[x]=v[x]*y%MOD;
ch[x]=ch[x]*y%MOD;
}
inline void ud(int x){
v[x]=(v[x<<1]+v[x<<1|1])%MOD;
}
inline void pd(int x){
if(ch[x]!=1){
toch(x<<1,ch[x]);
toch(x<<1|1,ch[x]);
ch[x]=1;
}
}
void build(int x,int y,int z){
ch[x]=1;
if(y==z){
v[x]=s[y]*tim[y]%MOD;
return ;
}
int mid=y+z>>1;
build(x<<1,y,mid);
build(x<<1|1,mid+1,z);
ud(x);
}
void change(int x,int y,int z,int l,int r,ll cv){
if(y==l&&z==r){
toch(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
change(x<<1,y,mid,l,r,cv);
}else if(l>mid){
change(x<<1|1,mid+1,z,l,r,cv);
}else{
change(x<<1,y,mid,l,mid,cv);
change(x<<1|1,mid+1,z,mid+1,r,cv);
}
ud(x);
}
int main(){
int i,x,y;
scanf("%d%d",&n,&m);
s[0]=1;
ll t=0;
for(i=1;i<n;i++){
tim[i]=2*mi(3,n-i-1);
}
tim
=1;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
s[i]=s[i-1]*a[i]%MOD;
(t+=s[i])%=MOD;
}
build(1,1,n);
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
change(1,1,n,x,n,ni(a[x])*(a[x]=y)%MOD);
printf("%lld\n",v[1]);
}
return 0;
}

/*
5 5
9384 887 2778 6916 7794
2 8336
5 493
3 1422
1 28
4 60

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: