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. 关于Visual Studio 2010自动添加头部注释信息

    作为一个万年潜水党,不关这一篇文章技术含量如何,也算是一个好的开始吧.   在日常的开发中我们经常需要为类库添加注释和版权等信息,这样我们就需要每次去拷贝粘贴同样的文字,为了减少这种重复性的工作,我们 ...

  2. android ui界面设计参数讲解

    百度文库: http://wenku.baidu.com/link?url=s66Hw6byBEzmjL77doYL1YQN4Y_39F7MovaHKs5mVGrzTDOQCAmiM-1N_6Cdm- ...

  3. tp5---auth权限搭建2

    1.auth权限 composer auth库 下载完成之后 根据auth.php中所提及怎样创建表,就怎样建表 2.安利一个简单的建表操作 根据composer下载里的文件注释的代码,将其直接放到s ...

  4. docker教程目录

    为什么要用 Docker 什么是 Docker Docker 镜像 Docker容器的运用 Docker仓库 Docker如何获取镜像 CentOS 安装Docker Docker 列出镜像 Dock ...

  5. 常见ADB命令

    常见ADB命令 比如说知道了push和pull操作,就可以实现一个简单的手机助手. 如果有多台设备,操作的时候要指定设备.  -s加设备名称

  6. mysql外键理解

    一个班级的学生个人信息表: 什么是外键 在设计的时候,就给表1加入一个外键,这个外键就是表2中的学号字段,那么这样表1就是主表,表2就是子表. 外键用来干什么 为了一张表记录的数据不要太过冗余. 这和 ...

  7. customs event

    // First create the event var myEvent = new CustomEvent("userLogin", { detail: { username: ...

  8. Kotlin------数据类型和语法

    今天简单的来介绍Kotlin的基本语法.编程语言大多相通的,会基础学起来都很快,理论都一样,实现的代码语言不一样而已. 数值类型 Kotlin 处理数值的方法和 java 很相似,但不是完全一样.比如 ...

  9. HDU 4665 Mutiples on a circle (圆环DP)

    题意 N个数的圆环上有多少种方案可以使得选出来的一段数是K的倍数(N<=50000, K<=200, a[i]<=1000). 思路 多校第七场1004.圆上的DP--大脑太简单处理 ...

  10. 在阿里云服务器上配置CentOS+Nginx+Python+Flask环境

    在阿里云服务器上配置CentOS+Nginx+Python+Flask环境 项目运行环境 阿里云(单核CPU, 1G内存, Ubuntu 14.04 x64 带宽1Mbps), 具体购买和ssh连接阿 ...