2018牛客网暑假ACM多校训练赛(第十场)D Rikka with Prefix Sum 组合数学
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-D.html
题目传送门 - https://www.nowcoder.com/acm/contest/148/D
题意
多组数据。
给定一个长度为 $n$ 初始全为 $0$ 的数列 $A$ 。$m$ 次操作,要求支持以下三种操作。
1. 区间加一个数 $v$
2. 全局修改,对于每一个 $i$ ,把 $A_i$ 改成原序列前 $i$ 项的和。
3. 区间求和。(询问次数不超过500)
$n,m\leq 10^5,v\leq 10^9$
题解
我们首先考虑在位置 $x$ 的一个数 $v$ ,在取 $k$ 次前缀和之后,对位置为 $y$ 的数的贡献为多少?
令 $L=y-x+1$ ,随便推式子或者打个表都可以得到贡献为:
$$\binom{(k-1)+(L-1)}{k-1}v$$
预处理组合数。由于询问次数 $\leq 500$ ,我们如果可以 $O(m)$ 回答每一个询问,那么就非常给力了。
由于区间修改的操作数太多了,所以我们取差分数组(一次反前缀和),在差分数组上做两次单点修改即可完成区间修改。
同理,区间询问我们不可能把每一个点的答案都算出来,我们取前缀和,于是区间询问就可以拆成两个单点询问,通过差分搞定了。
至于这个如何实现取前缀和数组,和取反前缀和数组,只需要记录一下当前的前缀和次数 $k$ 。
遇到操作 2 的时候 k++ 即可。
遇到操作 1 的时候,把单点修改的操作记下来,需要记录当前修改位置,修改值,当前修改时,取了几次前缀和。
时间复杂度 $O(mq)$ 。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=200005,mod=998244353;
int read(){
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
int T,n,m;
struct Point{
int x,k,v;
Point(){}
Point(int _x,int _y,int _v){
x=_x,k=_y,v=_v;
}
}o[N];
int ocnt,k;
int Fac[N],Inv[N];
int C(int n,int m){
if (m<0||m>n)
return 0;
return 1LL*Fac[n]*Inv[m]%mod*Inv[n-m]%mod;
}
void add(int &x,int y){
x+=y;
if (x>=mod)
x-=mod;
}
int solve(int x){
k+=2;
int res=0;
for (int i=1;i<=ocnt;i++)
if (o[i].x<x)
res=(1LL*o[i].v*C(k-o[i].k+x-o[i].x-1,k-o[i].k-1)+res)%mod;
else if (o[i].x==x)
add(res,o[i].v);
k-=2;
return res;
}
int main(){
Fac[0]=Inv[0]=1;
for (int i=1;i<N;i++){
Fac[i]=1LL*Fac[i-1]*i%mod;
Inv[i]=Pow(Fac[i],mod-2);
}
scanf("%d",&T);
while (T--){
n=read(),m=read();
ocnt=0,k=-1;
for (int i=1;i<=m;i++){
int opt=read(),L,R,v;
if (opt==2){
k++;
continue;
}
L=read(),R=read();
if (opt==1){
v=read();
o[++ocnt]=Point(L,k,v);
o[++ocnt]=Point(R+1,k,(mod-v)%mod);
}
if (opt==3)
printf("%d\n",(solve(R)-solve(L-1)+mod)%mod);
}
}
return 0;
}
2018牛客网暑假ACM多校训练赛(第十场)D Rikka with Prefix Sum 组合数学的更多相关文章
- 2018牛客网暑假ACM多校训练赛(第二场)E tree 动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round2-E.html 题目传送门 - 2018牛客多校赛第二场 E ...
- 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-I.html 题目传送门 - 2018牛客多校赛第三场 I ...
- 2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-G.html 题目传送门 - 2018牛客多校赛第三场 G ...
- 2018牛客网暑假ACM多校训练赛(第三场)D Encrypted String Matching 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-D.html 题目传送门 - 2018牛客多校赛第三场 D ...
- 2018牛客网暑假ACM多校训练赛(第十场)H Rikka with Ants 类欧几里德算法
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-H.html 题目传送门 - https://www.n ...
- 2018牛客网暑假ACM多校训练赛(第十场)F Rikka with Line Graph 最短路 Floyd
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-F.html 题目传送门 - https://www.n ...
- 2018牛客网暑假ACM多校训练赛(第八场)H Playing games 博弈 FWT
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round8-H.html 题目传送门 - https://www.no ...
- 2018牛客网暑假ACM多校训练赛(第七场)I Tree Subset Diameter 动态规划 长链剖分 线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round7-I.html 题目传送门 - https://www.n ...
- 2018牛客网暑假ACM多校训练赛(第六场)I Team Rocket 线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round6-I.html 题目传送门 - https://www.no ...
随机推荐
- ls 命令
命令: ls 对应英文: list 作用: 查看当前文件夹下的内容 选项: -a 查看隐藏文件, 文件名前带 . 号的文件 -l 以详细列表形式显示 -h 人性化方式显示文件大小(注:-h必须和-l同 ...
- MQ选型之RabbitMQ
RabbitMQ是部署最广泛的开源消息代理.[官方原话] 前言: MQ 是什么?队列是什么,MQ 我们可以理解为消息队列(message queue),队列我们可以理解为管道.以管道的方式做消息传递. ...
- Go代码重构:23倍的性能爆增
几周前,我读了一篇名为“ Good Code vs Go Code中的错误代码 ”的文章,作者指导我们逐步完成实际业务用例的重构. 本文的重点是将“坏代码”转变为“良好代码”:更具惯用性,更易读,利用 ...
- Confluence 6 数据库表-空间(Spaces)
这个表格与空间的管理有关. spaces 有关空间使用的信息:key,空间的名称和数字 ID. https://www.cwiki.us/display/CONF6ZH/Confluence+Data ...
- Confluence 6 外部小工具在其他应用中设置可信关系
为了在你的 Confluence 中与其他应用建立外部小工具,我们建议你在 2 个应用之间设置 OAuth 或者信任的应用连接关系.在这个例子中,外部应用为小工具的服务器(服务器提供者)和 Confl ...
- 【Linux】基本命令操作
一.用户操作 1.新增用户 useradd -u 1101 -g zte -d /home/xhs -m xhs --其中,1101,为用户ID,尽量使用500以上的 zte,为用户组 /home/x ...
- python网络爬虫笔记(九)
4.1.1 urllib2 和urllib是两个不一样的模块 urllib2最简单的就是使用urllie2.urlopen函数使用如下 urllib2.urlopen(url[,data[,timeo ...
- cf909C 线性dp+滚动数组好题!
一开始一直以为是区间dp.. /* f下面必须有一个s 其余的s可以和任意f进行匹配 所以用线性dp来做 先预处理一下: fffssfsfs==>3 0 1 1 dp[i][j] 表示第i行缩进 ...
- fdisk命令
fdisk -l命令详解 Disk /dev/sda: 53.7 GB, 53687091200 bytes 块设备名称为/dev/sda,此设备的大小为53.7GB,这个数字不是特别精确,我系统是5 ...
- 阿里云人脸识别测试接口出错 返回Body:{ "errno": 3002, "err_msg": "ILLEGAL_PARAMETERS", "request_id": "672cba83-cf93-4ef4-9ce5-d87e51601632" }
错误信息如下 返回Body:{ "errno": 3002, "err_msg": "ILLEGAL_PARAMETERS", ...... ...