「SHOI2016」随机序列]
\(Description\)
你的面前有\(n\)个数排成一行,分别为\(a_{1},a_{2},a_{3}......,a_{n}\)。你打算在每相邻的两个\(a_{i}\)和\(a_{i+1}\)间都插入一个加号、减号或者乘号。那么一共有\(3^{n-1}\)种可能的表达式。 你对所有可能的表达式的值的和非常感兴趣。但这毕竟太简单了,所以你还打算支持一个修改操作,可以修改某个\(a_{i}\)的值。 你能够编写一个程序对每个修改都输出修改完之后所有可能表达式的和吗?注意,修改是永久的,也就是说每次修改都是在上一次修改的基础上进行,而不是在最初的表达式上进行。
\(Input\)
第一行包含两个正整数\(n\)和\(q\),为数的个数和询问的个数。
第二行包含\(n\)个非负整数,依次表示\(a_{1},a_{2},a_{3}......,a_{n}\)。
接下来\(q\)行,每行包含两个非负整数\(t\)和\(v\),表示要将\(a_{t}\)修改为\(v\),其中\(1<=t<=n\)。
保证对于\(1<=j<=n,1<=i<=q\),都有\(a_{j},v_{i}<=10^4\) 。
\(Output\)
输出\(q\)行。对于每个修改输出一行,包含一个整数,表示修改之后所有可能表达式的和,对\(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
\(Hint\)
对于\(20%\)的数据,\(n,q<=20\)
对于\(50%\)的数据,\(n,q<=1000\)
对于\(100%\)的数据,\(n,q<=100000\)
思路
首先我们可以考虑,对于一个\(n=5\)情况下
肯定会有\(\begin{cases}a_{1}*a_{2}+a_{3}*a_{4}-a_{5}\\a_{1}*a_{2}-a_{3}*a_{4}+a_{5}\\\end{cases}\)
这样一对相反的式子,其中求和之后就只剩下\(a_{1}*a_{2}\)这种形式的前缀积
对于每个式子,都肯定会有与他相反的式子,于是最后只用求所有的前缀积的和就好了
但是怎么求前缀积的和呢
我们首先定义\(a(1)\)后面的符号位为第一符号位,\(a(2)\)后面的为第二符号位,以此类推
可以得到一共有4个符号位,其中没有第五符号位
我们令\(g(i)=\prod\limits_{j=1}^ia_j\),也就是从\(1\)到\(i\)的\(a_{i}\)的乘积。
设\(f(i)\)为\(g(i)\)出现的个数
可以发现\(g(5)=a1*a2*a3*a4*a5\),这种情况下,\(f(5)=1\)
那么,\(g(4)\)的情况就是由\(g(5)\)中的第四符号位变成减号或加号所组成:
\(\begin{cases}a_{1}*a_{2}*a_{3}*a_{4}-a_{5}\\a_{1}*a_{2}*a_{3}*a_{4}+a_{5}\\\end{cases}\)
所以\(f(4)=2\)
同理,\(g(3)\)就是由\(g(4)\)中的第三符号位变成加号或减号,第四符号位变成加号、减号、乘号
所以\(f(3)=6\),即 \(2\times3=6\)
易得,\(f(2)=2\times3\times3=18\),\(f(1)=2\times3\times3\times3=54\)
所以我们可以得到关于\(f(x)\)的通项:
\(f(x)=\begin{cases}1&x=1\\2&x=2\\f(x+1)\times3&x>2\end{cases}\)
所以,我们可以轻易\(O(n)\)计算出\(g(i)\)和\(f(i)\)
接着建一棵线段树,每个节点维护\(\sum\limits_{i=l}^{r}g(i)*f(i)\)的值
最后询问时输出根节点所存的值就好了
接下来我们看看修改操作怎么实现
比如,还是那五个数,将其中的\(a_{3}\)变成\(k\)
原式\(=f(1)*a_{1}+f(2)*a_{1}*a_{2}+f(3)*a_{1}*a_{2}*a_{3}+f(4)*a_{1}*a_{2}*a_{3}*a_{4}+f(5)*a_{1}*a_{2}*a_{3}*a_{4}*a_{5}\)
变成 \(f(1)*a_{1}+f(2)*a_{1}*a_{2}+f(3)*a_{1}*a_{2}*k+f(4)*a_{1}*a_{2}*k*a_{4}+f(5)*a_{1}*a_{2}*k*a_{4}*a_{5}\)
可以看到,受到影响的只有\(g(3),g(4),g(5)\)
于是,我们对于 \(3<=i<=5\) 的\(g(i)\)进行区间修改,每个乘上\(\frac{k}{a_{3}}\)就好了,在这里因为除法+取模,于是我们选择乘法逆元(大佬的博客,不是我的)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010,M=10010,mod=1e9+7;
typedef long long ll;
int n,q;
ll inv[M],g[N],f[N];
int a[N];
struct tree
{
long long val,tag;
}t[N<<2];
void up(int k)
{
t[k].val=(t[k<<1].val+t[k<<1|1].val)%mod;
}
void build(int k,int l,int r)
{
t[k].tag=1;
if(l==r)
{
t[k].val=g[l]*f[l]%mod;
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
up(k);
}
void pushdown(int k)
{
if(t[k].tag!=1)
{
t[k<<1].val=(t[k<<1].val*t[k].tag)%mod;
t[k<<1].tag=(t[k<<1].tag*t[k].tag)%mod;
t[k<<1|1].val=(t[k<<1|1].val*t[k].tag)%mod;
t[k<<1|1].tag=(t[k<<1|1].tag*t[k].tag)%mod;
t[k].tag=1;
}
}
void modify(int k,int l,int r,int x,int y,ll d)
{
if(x<=l&&r<=y)
{
t[k].val=(t[k].val*d)%mod;
t[k].tag=(t[k].tag*d)%mod;
return ;
}
pushdown(k);
int mid=(l+r)>>1;
if(x<=mid)modify(k<<1,l,mid,x,y,d);
if(y>mid)modify(k<<1|1,mid+1,r,x,y,d);
up(k);
}
int main()
{
scanf("%d %d",&n,&q);
inv[0]=0,inv[1]=1;
for(int i=2;i<=M;i++)inv[i]=inv[mod%i]*1ll*(mod-mod/i)%mod;
ll sum=1;
f[n]=1,f[n-1]=2;
for(int i=n-2;i>=1;i--)f[i]=(f[i+1]*3)%mod;
g[0]=1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
g[i]=(g[i-1]*1ll*a[i])%mod;
}
build(1,1,n);
int p,v;
for(int i=1;i<=q;i++)
{
scanf("%d %d",&p,&v);
modify(1,1,n,p,n,1ll*v*inv[a[p]]%mod);
a[p]=v;
printf("%lld\n",t[1].val);
}
return 0;
}
原文地址:https://www.cnblogs.com/ShuraEye/p/11770690.html
- MySQL中的derived table(r12笔记第47天)
- Oracle数据库端口突然无法访问的分析(r12笔记第46天)
- MySQL中的反连接(r12笔记第45天)
- Nginx配置多站点下的Proxy_cache或Fastcgi_cache缓存加速
- MySQL主从不一致的细小问题分析(r12笔记第62天)
- Linux在批量服务器管理中实用的PS1命令提示符格式
- Golang语言社区-并发模型和应用场景
- 翻过那座山,就能看见海|kubernetes让DBA更优雅地管理数据库
- 基于TextCNN的谩骂评论识别模型
- Golang语言社区-文件操作
- MySQL service启动脚本浅析(r12笔记第59天)
- 分享WordPress显示评论者IP的归属地及运营商信息的2种方案
- 解决dos2unix/unix2dos报错,并在家目录下生成u2dtmp*文件问题
- 【前沿】TensorFlow Pytorch Keras代码实现深度学习大神Hinton NIPS2017 Capsule论文
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter框架分析(二)-- 初始化
- Flutter框架分析(三)-- Widget,Element和RenderObject
- 傅里叶变换的图像应用--学好了用处大~
- Flutter框架分析(四)-- Flutter框架的运行
- R海拾遗-流程图prismadiagramR
- R海拾遗-单项重复测量方差分析
- R海拾遗-双因素重复测量方差分析
- 小白秒变大神--windows窗口+装B神器大全 两部曲
- R海拾遗-三因素重复
- 推荐一种简单的在Flutter中分离View与Model的方法
- R海拾遗-tidyverse
- Flutter Hooks 使用及原理
- ggplot2_总纲
- 聊聊怎样学习Binder
- ggplot2_散点图