標籤:
Description你的面前有N個數排成一行。分別為A1, A2, … , An。你打算在每相鄰的兩個 Ai和 Ai+1 間都插入一個加號或者減號或者乘號。那麼一共有 3^(n-1) 種可能的運算式。你對所有可能的運算式的值的和非常感興趣。但這畢竟太簡單了,所以你還打算支援一個修改操作,可以修改某個Ai 的值。你能夠編寫一個程式對每個修改都輸出修改完之後所有可能運算式的和嗎?注意,修改是永久的,也就是說每次修改都是在上一次修改的基礎上進行, 而不是在最初的運算式上進行。
Input第一行包含 2 個正整數 N 和 Q,為數的個數和詢問的個數。接下來一行 n 個非負整數,依次表示a1,a2...an在接下來 Q 行,其中第 ?? 行兩個非負整數Ti 和Vi,表示要將 Ati 修改為 Vi。其中 1 ≤ Ti ≤ N。保證對於 1 ≤ J ≤ N, 1 ≤ i≤ Q,都有 Aj,Vi ≤ 10^4。N,Q<=100000,本題僅有三組資料
Output輸出共 Q 行,其中第 i 行表示第 i 個詢問之後所有可能運算式的和,對10^9 + 7 模數。 題解首先想到+、-號會導致後面的所有結果相互抵消。所以對答案有貢獻的是前面一直是連乘的部分。即第一個非乘號的前面部分所以我們只需要維護首碼積,修改的時候線段樹區間修改,先預先處理逆元就可以做了我認為這道題最關鍵的地方就是+、-號相互抵消,一下子簡化了問題。一開始想是否有規律,真實太蠢了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 100020 7 8 typedef long long ll; 9 const ll mod = 1e9 + 7;10 struct node{11 int ls,rs;12 ll sum,mul;13 }sgt[maxn * 4];14 ll inv[maxn],fac[maxn],sum[maxn],pow[maxn];15 int n,a[maxn],q,rt,tot;16 17 inline ll power(ll x,int y){18 ll res = 1;19 while ( y ){20 if ( y & 1 ) res = res * x % mod;21 x = x * x % mod;22 y >>= 1;23 }24 return res % mod;25 }26 void init(){27 for (int i = 1 ; i <= 10000 ; i++) inv[i] = power(i,mod - 2);28 pow[0] = 1;29 for (int i = 1 ; i <= 100000 ; i++) pow[i] = pow[i - 1] * 3ll % mod;30 }31 inline void update(int x){32 sgt[x].sum = sgt[sgt[x].ls].sum + sgt[sgt[x].rs].sum;33 if ( sgt[x].sum >= mod ) sgt[x].sum -= mod;34 }35 void build(int &x,int l,int r){36 x = ++tot;37 sgt[x].mul = 1;38 if ( l == r ){39 if ( l == n ) sgt[x].sum = sum[l];40 else sgt[x].sum = sum[l] * pow[n - l - 1] * 2ll % mod;41 return;42 }43 int mid = (l + r) >> 1;44 build(sgt[x].ls,l,mid);45 build(sgt[x].rs,mid + 1,r);46 update(x);47 }48 inline void mul(int x,ll d){49 sgt[x].sum = sgt[x].sum * (ll)d % mod;50 sgt[x].mul = sgt[x].mul * (ll)d % mod; 51 }52 inline void pushdown(int x){53 if ( sgt[x].mul != 1 ){54 mul(sgt[x].ls,sgt[x].mul);55 mul(sgt[x].rs,sgt[x].mul);56 sgt[x].mul = 1;57 }58 }59 void modify(int x,int l,int r,int ls,int rs,ll d){60 if ( ls <= l && rs >= r ){61 mul(x,d);62 return;63 }64 pushdown(x);65 int mid = (l + r) >> 1;66 if ( ls <= mid ) modify(sgt[x].ls,l,mid,ls,rs,d);67 if ( rs > mid ) modify(sgt[x].rs,mid + 1,r,ls,rs,d);68 update(x);69 }70 int main(){71 //freopen("input.txt","r",stdin);72 scanf("%d %d",&n,&q);73 init();74 for (int i = 1 ; i <= n ; i++){75 scanf("%d",&a[i]);76 }77 sum[0] = 1;78 for (int i = 1 ; i <= n ; i++) sum[i] = a[i] * sum[i - 1] % mod;79 build(rt,1,n);80 while ( q-- ){81 int id,v;82 scanf("%d %d",&id,&v);83 modify(rt,1,n,id,n,inv[a[id]]);84 modify(rt,1,n,id,n,v);85 a[id] = v;86 printf("%lld\n",sgt[rt].sum);87 }88 return 0;89 }
bzoj 4597 隨機序列