zoukankan      html  css  js  c++  java
  • SHOI2016 随机序列

    给你一个数列,在相邻两个数之间插入加号,减号或乘号

    每次支持单点修改,求所有这样可以得到的表达式之和,膜1e9 + 7

    sol:

    我是个 sb 。。。

    可以发现,如果某位置出现了加号,后面一定有一个减号把它消掉,于是答案就是一些出现了好几次的前缀积之和

    算一下每段前缀积的贡献即可

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    int n,q;
    const int mod = 1e9 + 7,maxn = 1e5 + 10;
    int a[maxn],fac[maxn];
    #define ls (x << 1)
    #define rs ((x << 1) | 1)
    int seg[maxn << 2],tag[maxn << 2];
    inline int pw(int x,int t)
    {
        int res = 1;x %= mod;
        while(t)
        {
            if(t & 1)res = res * x % mod;
            x = x * x % mod;
            t = t >> 1;
        }
        return res;
    }
    inline void build(int x,int l,int r)
    {
        tag[x] = 1;
        if(l == r)seg[x] = fac[l];
        else
        {
            int mid = (l + r) >> 1;
            build(ls,l,mid);build(rs,mid + 1,r);
            seg[x] = (seg[ls] + seg[rs]) % mod;
        }    
    }
    inline void pushdown(int x,int l,int r)
    {
        if(tag[x] != 1)
        {
            (tag[ls] *= tag[x]) %= mod;(tag[rs] *= tag[x]) %= mod;
            (seg[ls] *= tag[x]) %= mod;(seg[rs] *= tag[x]) %= mod;
            tag[x] = 1;
        }
    }
    inline void update(int x,int l,int r,int L,int R,int val)
    {
        if(L <= l && r <= R)
        {
            (seg[x] *= val) %= mod;
            (tag[x] *= val) %= mod;
            return;
        }
        pushdown(x,l,r);
        int mid = (l + r) >> 1;
        if(L <= mid)update(ls,l,mid,L,R,val);
        if(R > mid)update(rs,mid + 1,r,L,R,val);
        seg[x] = (seg[ls] + seg[rs]) % mod;
    }
    signed main()
    {
        n = read(),q = read();
        for(int i=1;i<=n;i++)a[i] = read();
        int mul = 1;
        for(int i=1;i<=n;i++)
        {
            mul = (long long)mul * a[i] % mod;
            if(i == n)fac[i] = mul;
            else fac[i] = (long long)mul * 2 * pw(3, n - i - 1) % mod;
        }build(1,1,n);
        while(q--)
        {
            int p = read(),v = read();
            update(1,1,n,p,n,(long long)v * pw(a[p],mod - 2) % mod);
            a[p] = v;
            printf("%lld
    ",seg[1]);
        }
    }
    View Code

     $$sum_{i=1}^{n-1}sum_i imes 2 imes 3^{n-i-1} + sum_n$$

    $sum$ 数组为前缀积

  • 相关阅读:
    Content Hugging Priority 和 Content Compression Resistance Priority
    fiddler 拦截小结
    好的 iOS 代码习惯
    查看约束优先级的方法
    定义接口常用约定
    让系统照片选择器的导航栏变蓝的代码
    ZT C语言实现字符串倒序
    ZT 蓝牙的AVCTP协议笔记
    ZT 蓝牙的AVDTP协议笔记
    ZT A2DP协议笔记
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9887208.html
Copyright © 2011-2022 走看看