Loj 2028 随机序列

  • 连续的乘号会将序列分成若干个块,块与块之间用加减号连接:

\[(a_1*a_2*...a_i)\pm(a_{i+1}*a_{i+2}*...a_j)\pm...
\]

  • 除去所有都是乘号的一种,对于任意一个序列,总有与之对应唯一的另一个序列,它们所有的加减号都相反.
  • 把这两个序列的和相加,就只剩下了 \(2*(a_1*a_2*...a_i)\),其中 \(i\) 为第一个加减号之前的位置.
  • 那么平均下来,相当于每个序列的贡献为 \((a_1*a_2*...a_i)\).
  • 考虑对每个 \(i\) ,前面填入了 \(i-1\) 个乘号,相邻的必须是加减号,后面 \(n-i-1\) 个符号随便填,共有 \(2*3^{n-i-1}\) 种.
  • 那么用线段树对于 \([1,n-1]\) 维护 \(v_i=3^{n-i-1}*2*\prod_{j=1}^i a_i\) 的和,答案即为

\[(\prod_{i=1}^{n}a_i)+(\sum_{i=1}^{n-1}v_i).
\]

  • 将位置 \(i\) 的数从 \(a\) 改为 \(b\) ,相当于对区间 \([i,n-1]\) 乘了 \(\frac b a\) .显然容易实现.
  • 注意修改位置 \(n\) 上的数时不用区间修改.否则 \(L>R\) ,会炸.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
int x=0;
bool pos=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
pos=0;
for(;isdigit(ch);ch=getchar())
x=x*10+ch-'0';
return pos?x:-x;
}
const int P=1e9+7;
const int MAXN=1e5+10;
const int MAXV=1e4;
int n,m;
inline int add(int a,int b)
{
return (a + b) % P;
}
inline int mul(int a,int b)
{
return 1LL * a * b % P;
}
int fpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=mul(res,a);
a=mul(a,a);
b>>=1;
}
return res;
}
int inv[MAXV+10],Pow[MAXN];
int a[MAXN],prod[MAXN];
struct node{
int l,r;
int sum,tag;
node()
{
tag=1;
}
}Tree[MAXN<<2];
#define root Tree[o]
#define lson Tree[o<<1]
#define rson Tree[o<<1|1]
void pushup(int o)
{
root.sum=add(lson.sum,rson.sum);
}
void BuildTree(int o,int l,int r)
{
root.l=l,root.r=r;
if(l==r)
{
//fpow(3,n-l-1) Pow[n-l-1]
int tmp=mul(Pow[n-l-1],2);
tmp=mul(tmp,prod[l]);
root.sum=tmp;
return;
}
int mid=(l+r)>>1;
BuildTree(o<<1,l,mid);
BuildTree(o<<1|1,mid+1,r);
pushup(o);
}
void Modifiy(int o,int c)
{
root.sum=mul(root.sum,c);
root.tag=mul(root.tag,c);
}
void pushdown(int o)
{
if(root.tag!=1)
{
Modifiy(o<<1,root.tag);
Modifiy(o<<1|1,root.tag);
root.tag=1;
}
}
void update(int o,int L,int R,int c)
{
int l=root.l,r=root.r;
if(l>R || r<l)
return;
if(L<=l && r<=R)
{
Modifiy(o,c);
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(L<=mid)
update(o<<1,L,R,c);
if(R>mid)
update(o<<1|1,L,R,c);
pushup(o);
}
void init()
{
inv[1]=1;
for(int i=2;i<=MAXV;++i)
inv[i]=mul(P-P/i,inv[P%i]);
Pow[0]=1;
for(int i=1;i<=n;++i)
Pow[i]=mul(Pow[i-1],3);
}
int main()
{
n=read(),m=read();
init();
prod[0]=1;
for(int i=1;i<=n;++i)
prod[i]=mul(prod[i-1],a[i]=read());
BuildTree(1,1,n-1);
while(m--)
{
int i=read(),v=read();
int c=mul(v,inv[a[i]]);
a[i]=v;
prod[n]=mul(prod[n],c);
if(i<=n-1)
update(1,i,n-1,c);
int ans=add(Tree[1].sum,prod[n]);
printf("%d\n",ans);
}
return 0;
}

Loj 2028 随机序列的更多相关文章

  1. SHOI做题记录

    LOJ #2027. 「SHOI2016」黑暗前的幻想乡 考虑到每个公司一条边,那就等价于没有任何一家公司没有边. 然后就可以容斥+矩阵树定理,没了. LOJ #2028. 「SHOI2016」随机序 ...

  2. 【LOJ】#2028. 「SHOI2016」随机序列

    题解 我们发现只有从第一个往后数,用乘号联通的块是有贡献的 为什么,因为后面所有表达式 肯定会有 + ,还会有个-,贡献全都被抵消了 所以我们处理出前缀乘积,然后乘上表达式的方案数 答案就是\(\su ...

  3. 随机序列生成算法---生成前N个整数的一组随机序列

    问题描述: 给定输入N,生成从1开始的:1,2,3,4,......N 一组随机序列,序列中的数不能重复出现. 比如:N=5,合法的随机序列为{4,3,1,5,2} .{3,1,4,2,5}……非法的 ...

  4. [OpenJudge 3066]随机序列

    [OpenJudge 3066]随机序列 试题描述 Bob喜欢按照如下规则生成随机数: 第一步:令a[0] = S, 当n = 0: 第二步:a[n+1] = (a[n]*A+B)%P: 第三步:如果 ...

  5. hrbust oj 1526+2028 树状数组

    冒泡排序中 如果一个数的后面的某个数和这个数不符合排序规则 那么这个数就会在未来的某次冒泡中与那个数进行交换 这里用到了 树状数组求逆序数的办法来做 需要注意的是2028并不可以改完数组大小后直接套1 ...

  6. [Noi2016]区间 BZOJ4653 洛谷P1712 Loj#2086

    额... 首先,看到这道题,第一想法就是二分答案+线段树... 兴高采烈的认为我一定能AC,之后发现n是500000... nlog^2=80%,亲测可过... 由于答案是求满足题意的最大长度-最小长 ...

  7. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  8. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  9. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

随机推荐

  1. CentOS7配置自定义JDK

    由于选择的是centos7-dvd镜像自带了open jdk,需要卸载.首先查询自带的jdk: rpm -qa | grep java 会出现7个带有java名称的东西,删除其中的带有openjdk字 ...

  2. Excel转化成DataTable实现:NPOI和OLEDb

    使用两种方式实现的excel数据转化成DataSet,再结合前一篇的DataTable转化为实体,就可以解决excel到实体之间的转化. 代码如下: 首先定义一个接口: public interfac ...

  3. shell中的常用通配符,字符类

    因为 shell 频繁 地使用文件名,shell 提供了特殊字符来帮助你快速指定一组文件名.这些特殊字符叫做通配符. 通配符         意义 * 匹配任意多个字符(包括零个或一个) ? 匹配任意 ...

  4. replace()函数用法

    replace()函数表示将用一个字符串替换字符串中的所出现的特定内容. 语法为:replace(字段1,字段2,字段3),意思为字段3将会替换字段1里与字段2相同的内容  列如: table1 st ...

  5. iview--2

    安装iview 接下来进行配置 按照手册 https://www.iviewui.com/docs/guide/start 引入iView 打开我的项目,出现了这么多的错 解决这个问题的办法 如果你用 ...

  6. hapRroxy 安装配置详解

    简介 HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要 ...

  7. label技巧

    问题描述: 一般都用label的for属性指定label的点击范围: <label for="male"><input type="radio" ...

  8. 将封装了envi功能的IDL类导出成java类,方便java调用

    目的:     用IDL将ENVI的功能封装成为IDL的类,并使用IDL的对象导出功能把这些功能类导出为java类,方便java调用.(本来想直接通过GP工具调用的,但是没有授权文件)   操作步骤: ...

  9. Prism 4 文档 ---第2章:初始化Prism应用程序

     这一章节介绍Prism应用程序启动和运行时发生的内容.Prism应用程序在启动时需要有注册和配置的过程,这就是所谓的自自启动程序. 什么是自启动引导程序?     引导程序是一个类,它负责使用Pri ...

  10. 【javascript基础】函数前面的一元操作符

    在函数前面加:+  ;  ~ !  - 等等一元操作符,javascript 引擎都会将后面的statement转换成表达式(expression),这样就可以调用了.