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 取模。

Sample Input

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

Sample Output

890543652
252923708
942282590
228728040
608998099
 
一颗赛艇,我是这么推的结论:
首先考虑暴力DP,设S[i]表示∏j<=i Aj。f[i]表示前i个数在之间随便插数的结果之和,不难得到f[i]=∑j<i (2*f[j]) + S[i]。
然后3*f[i]-S[i]=∑j<=i (2*f[j]) 
f[i+1]=∑j<=i (2*f[j]) + S[i+1]
        =3*f[i] (-S[i]+S[i+1])
考虑每个S[i]-S[i-1]对f[n]的影响,则f[n]=∑(S[i]-S[i-1])*3^(n-i)。
裂项一下,则f[n]=2*∑(S[i]*3^(n-i-1))+S[n]。
然后就可以用线段树简单维护一下答案了。
然后又想了一下,发现答案可以这样理解:枚举第一串*号拓展到哪个位置,除了放了n-1个*号的情况,下一步放+和放-号的答案刚好抵消,所以对答案的贡献刚好是S[i]*3^(n-i-1)。
膜。的。长。者。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=100010;
const int mod=1000000007;
ll pow(ll n,int m) {
ll ans=1;
for(;m;m>>=1,(n*=n)%=mod) if(m&1) (ans*=n)%=mod;
return ans;
}
int n,q,A[maxn],xp[maxn];
ll pown,inv3,sumk[maxn<<2],sumv[maxn<<2];
void maintain(int o,int l,int r) {
int mid=l+r>>1,lc=o<<1,rc=lc|1;
sumk[o]=sumk[lc]*sumk[rc]%mod;
sumv[o]=(sumv[lc]+sumv[rc]*xp[mid-l+1]%mod*sumk[lc])%mod;
}
void build(int o,int l,int r) {
if(l==r) sumk[o]=A[l],sumv[o]=A[l]*pown%mod;
else {
int mid=l+r>>1,lc=o<<1,rc=lc|1;
build(lc,l,mid);build(rc,mid+1,r);
maintain(o,l,r);
}
}
void update(int o,int l,int r,int p) {
if(p==n) {A[n]=read();return;}
if(l==r) sumk[o]=read(),sumv[o]=sumk[o]*pown%mod;
else {
int mid=l+r>>1,lc=o<<1,rc=lc|1;
if(p<=mid) update(lc,l,mid,p);
else update(rc,mid+1,r,p);
maintain(o,l,r);
}
}
int main() {
n=read();q=read();xp[0]=1;inv3=pow(3,mod-2);pown=pow(3,n-2);
rep(i,1,n) A[i]=read(),xp[i]=xp[i-1]*inv3%mod;
build(1,1,n-1);
rep(i,1,q) {
update(1,1,n-1,read());
printf("%lld\n",(sumv[1]*2+sumk[1]*A[n])%mod);
}
return 0;
}

  

BZOJ4597: [Shoi2016]随机序列的更多相关文章

  1. BZOJ4597 SHOI2016随机序列(线段树)

    先考虑题目所说的太简单了的问题.注意到只要把加减号相取反,就可以得到一对除了第一项都互相抵消的式子.于是得到答案即为Σf(i)g(i),其中f(i)为前缀积,g(i)为第i个数前面所有符号均填乘号,第 ...

  2. 【BZOJ4597】[Shoi2016]随机序列 线段树

    [BZOJ4597][Shoi2016]随机序列 Description 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者减号 ...

  3. P4340 [SHOI2016]随机序列

    题目 P4340 [SHOI2016]随机序列 思维好题 做法 是否觉得水在于你是否发现加减是会抵消的,所以我们只用考虑乘的部分 一块乘只能前面无号(也就是前缀形式)才统计,所以用线段树维护区间前缀乘 ...

  4. BZOJ 4597: [Shoi2016]随机序列

    4597: [Shoi2016]随机序列 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 255  Solved: 174[Submit][Status ...

  5. BZOJ4597:[SHOI2016]随机序列——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4597 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 ...

  6. 【bzoj4597】 [Shoi2016]随机序列

    可以发现加减号之间可以互相抵消. 真正加到答案里的只有一些前缀积. 记s[i]为a[1]*a[2]*a[3]...*a[i].那s[i]在答案中出现的次数就是2*3^(n-i-1); 修改一个数只会对 ...

  7. [洛谷P4340][SHOI2016]随机序列

    题目大意:有$n(n\leqslant10^5)$个数,每两个数之间可以加入$+-\times$三种符号,$q(q\leqslant10^5)$次询问,每次询问修改一个数后,所有表达式可能的值的和 题 ...

  8. SHOI2016 随机序列

    给你一个数列,在相邻两个数之间插入加号,减号或乘号 每次支持单点修改,求所有这样可以得到的表达式之和,膜1e9 + 7 sol: 我是个 sb ... 可以发现,如果某位置出现了加号,后面一定有一个减 ...

  9. bzoj 4597||洛谷P4340 [Shoi2016]随机序列

    https://www.lydsy.com/JudgeOnline/problem.php?id=4597 https://www.luogu.org/problemnew/show/P4340 妄图 ...

随机推荐

  1. 微软往年校招招面试题AC全解。

    因为4月初要参加微软的online.所以今天把微软的面试题拿出来做了,自己解答了题目.下面附上我的解答代码. -----------16年9月校招:  第一道题:Farthest Point(最远的整 ...

  2. websocket业务代码

    需求 用户登陆后,服务器实时推送用户的订单提醒,用websocket处理. 方案 两个js,notify-socket.js处理socket的连接,和socket的处理. nofify.js,做右下角 ...

  3. iOS getter setter

    getter setter 给成员变量起名字用的 setter方法 设置成员变量值 1. setter 方法一定是对象方法 不可能是类方法 2.一定没有返回值 3. 以set开头,并且set后面跟上需 ...

  4. ACID属性区别

    事务是指对系统进行的一组操作,为了保证系统的完整性,事务需要具有ACID特性,具体如下: 1. 原子性(Atomic)     一个事务包含多个操作,这些操作要么全部执行,要么全都不执行.实现事务的原 ...

  5. java多线程wait notify join

    wait notify 几个注意点: wait 与 notify/notifyAll 方法必须在同步代码块中使用,即要先对调用对象加锁. 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进 ...

  6. Servlet调用过程

    (1)在浏览器输入地址,浏览器先去查找hosts文件,将主机名翻译为ip地址,如果找不到就再去查询dns服务器将主机名翻译成ip地址. (2)浏览器根据ip地址和端口号访问服务器,组织http请求信息 ...

  7. 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。

    第一步: windows 8系统,运行aspx页面出现上述错误信息,解决办法如下: iis7 :控制面板->打开或关闭windows功能->Internet信息服务->万维网服务-& ...

  8. 给钛度产品的一些建议(Note)

    背景:上一只鼠标坏了,今天299从京东如了一只钛度鼠标,核心用料据说都很高端,设计也不错.但是实际用起来发现了很多码农常识问题和产品建议,遂反馈给钛度客服,并记录于此. 传送门: http://bbs ...

  9. 2016最后一贴,终于调通一个测试示例,并发现一个BUG???

    真的难点在于第一次调通.纠结五天,终于搞出界面. 也发现了一个书上代码,编辑用户时死活不通的情况,我将Links去了,改在data里,我X,,全OK了.. 原来的代码: onAdd: function ...

  10. Pugixml一种快速解析XML文件的开源解析库

    Pugixml是一个轻量级的C++ XML开源解析库,DOM形式的解析器.接口和丰富的遍历和修改操作,快速的解析,此外支持XPath1.0实现数据查询,支持unicode编码: 使用Pugixml可通 ...