zoukankan      html  css  js  c++  java
  • BZOJ4597: [Shoi2016]随机序列

    容易推出答案为$\,2sum_{i=1}^{n-1}3^{n-i-1}prod_{j=1}^{i}a_{j}+prod_{j=1}^{n}a_{j}\,$。然后线段树维护区间乘积和答案。我没多想直接用的区间乘区间和,有0会挂,而且模数必须是质数,然而做这题还是可以的。

    #include<cstdio>
    #define Z 
    int l=1,int r=n,int k=1
    #define N 100005
    #define M (l+r>>1)
    #define P (k<<1)
    #define S (k<<1|1)
    #define L l,M,P
    #define R M+1,r,S
    int n,m,s,t;
    typedef long long ll;
    const ll p=1e9+7;
    ll f[N],e[N],a[N];
    ll u[N*4],v[N*4];
    void apply(ll a,int k){
    	u[k]=u[k]*a%p;
    	v[k]=v[k]*a%p;
    }
    void devolve(int k){
    	if(v[k]!=1){
    		apply(v[k],P);
    		apply(v[k],S);
    		v[k]=1;
    	}
    }
    void update(int k){
    	u[k]=(u[P]+u[S])%p;
    }
    void build(Z){
    	if(l==r)
    		u[k]=a[l];
    	else{
    		build(L);
    		build(R);
    		update(k);
    	}
    	v[k]=1;
    }
    void amend(ll a,int s,int t,Z){
    	if(s<=l&&r<=t)
    		apply(a,k);
    	else{
    		devolve(k);
    		if(s<=M)
    			amend(a,s,t,L);
    		if(t>M)
    			amend(a,s,t,R);
    		update(k);
    	}
    }
    ll pow(ll u,ll k){
    	ll a=1;
    	for(;k;k>>=1){
    		if(k%2)a=a*u%p;
    		if(k/2)u=u*u%p;
    	}
    	return a;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)
    		scanf("%lld",e+i);
    	f[f[0]=a[0]=1]=2;
    	for(int i=2;i<n;++i)
    		f[i]=f[i-1]*3%p;
    	for(int i=1;i<=n;++i)
    		a[i]=a[i-1]*e[i]%p;
    	for(int i=1;i<=n;++i)
    		a[i]=a[i]*f[n-i]%p;
    	build();
    	while(m--){
    		scanf("%d%d",&s,&t);
    		t=t*pow(e[s],p-2)%p;
    		amend(t,s,n);
    		e[s]=e[s]*t%p;
    		printf("%lld
    ",u[1]);
    	}
    }
    
  • 相关阅读:
    Aizu
    Aizu
    POJ
    POJ
    POJ
    UVA
    manacher
    Gym
    Gym
    Gym
  • 原文地址:https://www.cnblogs.com/f321dd/p/5842964.html
Copyright © 2011-2022 走看看