Description

  你有一个长度为 \(n\) 的序列,第 \(i\) 项为 \(i\)。

  有 \(m\) 次操作,每次操作给定一个 \(x\),你需要将序列无限循环后截取前 \(x\) 项,作为新序列。

  问最后序列中每个数出现多少次。

  \(n,m\le 10^5,\space x_i\le 10^{18}\)

Solution

  有个很显然的性质:若存在 \(i,j\),满足 \(i\lt j\) 且 \(x_i\ge x_j\),则第 \(i\) 次操作没用,可以不做。

  所以简化后的操作序列 \(x\) 是单调上升的。

  (这步可以不写,因为按照下述做法,如果出现上述情况那在第 \(i\) 个操作不会对答案造成任何贡献)

  我们发现正着做不可行,考虑反着做。

  我们假设最后的序列不是无限循环得来的,比如对于样例,假设最后得到的序列是 1 2 3 4 5 6 7 8 9 10 11 12 13

  那么所谓的“无限循环”其实就是把一段区间模 \(x\)。

  依然以样例的操作为例,倒序做操作(忽略掉最后一个操作),倒数第二个操作的 \(x\) 为 \(8\)。

  那么显然第 \([9,13]\) 个数是由第 \([1,8]\) 个数循环得来的。

  故把第 \([9,13]\) 个数模 \(8\),得到新序列 1 2 3 4 5 6 7 8 1 2 3 4 5

  这时要把区间 \([1,8]\) 和区间 \([9,13]\) 分成两个独立区间扔进堆,因为以后 \([1,8]\) 区间再被模时,\([9,13]\) 区间作为 \([1,8]\) 区间的翻版,也可能被模。

  如果把样例的倒数第二个操作的 \(x\) 改为 \(5\) 呢?我们需要分出 \([1,5]\),\([6,10]\),\([11,13]\) 三个区间么?

  显然不用,\([1,5]\) 和 \([6,10]\) 两个区间显然等价,所以只记一个区间 \([1,5]\),然后系数 \(\times \space 2\) 即可。

  当一个区间长度被削到 \(\le n\) 时,设该区间长度为 \(len\),那么该区间内的数就是 \(1\) 到 \(len\) 了。其对答案的贡献是前缀 \(+\space 1\),差分即可(即在第 \(len\) 位上 \(+\space 1\),最后从第 \(n\) 位向第 \(1\) 位递推算一遍前缀和)。

  「这样做的时间复杂度对吗?」

  当然不对了,尝试用类似线段树的形态画出分割区间的过程,发现最优情况下都是一个 \(10^{18}\) 个元素的满二叉树……

  我们发现,当我们倒序扫到第 \(i\) 个操作时,我们会把很多个区间都分成长度为 \(x_i\) 和 \(len\% x_i\) 的两个区间。

  那我们为什么不再分出来的这些长度为 \(x_i\) 的区间再合成一个记呢?这样我们就只需要把长度为 \(len\% x_i\) 的区间再扔进堆了。

  这时复杂度就有意思了,这相当于初始时在堆中放入 \(n\) 个数 \(x_{1\cdots m}\),然后把每个数不停地模一个比自己小的数。

  这对应了一个很裸的性质:对于一个数,一直模比它小的数,最多模 \(\log n\) 次变成 \(1\),因为每模一次至少 \(÷\space 2\)。

  故堆中总共会出现过 \(m\log x_i\) 个元素,每次取堆顶元素的时间是 \(O(\log m)\),总时间为 \(O(m\log m\log x_i)\)。

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define N 100001
  4. using namespace std;
  5. inline ll read(){
  6. ll x=0; bool f=1; char c=getchar();
  7. for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
  8. for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
  9. if(f) return x;
  10. return 0-x;
  11. }
  12. int n,m,top; ll a[N],ans[N];
  13. struct scx{
  14. ll x,coe;
  15. inline bool operator <(const scx& a)const{
  16. return x<a.x;
  17. }
  18. }; priority_queue<scx> pq;
  19. int main(){
  20. n=a[0]=read(), m=read();
  21. ll x;
  22. for(int i=1; i<=m; ++i){
  23. x=read();
  24. while(top && a[top]>=x) --top;
  25. a[++top]=x;
  26. }
  27. pq.push((scx){a[top],1});
  28. for(int i=top-1; i>=0; --i){
  29. ll tmp = 0; scx u = pq.top();
  30. while(u.x>a[i]){
  31. pq.pop();
  32. tmp += (u.x/a[i])*u.coe, u.x %= a[i];
  33. if(u.x) pq.push(u);
  34. if(pq.empty()) break;
  35. u = pq.top();
  36. }
  37. if(tmp) pq.push((scx){a[i],tmp});
  38. }
  39. while(!pq.empty()){
  40. scx u = pq.top(); pq.pop();
  41. ans[u.x] += u.coe;
  42. }
  43. for(int i=n-1; i>=1; --i) ans[i]+=ans[i+1];
  44. for(int i=1; i<=n; ++i) printf("%lld\n",ans[i]);
  45. return 0;
  46. }

【AGC003 E】Sequential operations on Sequence的更多相关文章

  1. 【agc003E】Sequential operations on Sequence

    Portal -->agc003E Description 给你一个数串\(S\),一开始的时候\(S=\{1,2,3,...,n\}\),现在要对其进行\(m\)次操作,每次操作给定一个\(a ...

  2. 【47.40%】【codeforces 743B】Chloe and the sequence

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  3. 【codeforces 438D】The Child and Sequence

    [原题题面]传送门 [大致题意] 给定一个长度为n的非负整数序列a,你需要支持以下操作: 1:给定l,r,输出a[l]+a[l+1]+…+a[r]. 2:给定l,r,x,将a[l],a[l+1],…, ...

  4. 【做题】agc003E - Sequential operations on Sequence——经典结论

    题意:有一个序列,初始是从\(1\)到\(n\)的\(n\)个数.有\(q\)次操作,每次操作给出\(q_i\),把当前的序列重复无数遍,然后截取最前面的\(q_i\)个元素作为新序列.要求输出完成所 ...

  5. 【 CodeForces - 392C】 Yet Another Number Sequence (二项式展开+矩阵加速)

    Yet Another Number Sequence Description Everyone knows what the Fibonacci sequence is. This sequence ...

  6. 【BZOJ 2656】2656: [Zjoi2012]数列(sequence) (高精度)

    2656: [Zjoi2012]数列(sequence) Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 1499  Solved: 786 Descri ...

  7. 【Keras学习】Sequential模型

    序贯(Sequential)模型 序贯模型是多个网络层的线性堆叠,也就是“一条路走到黑”. 可以通过向Sequential模型传递一个layer的list来构造该模型: from keras.mode ...

  8. AtCoder Grand Contest 003 E - Sequential operations on Sequence

    题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_e 题目大意 一串数,初始为\(1\sim N\),现有\(Q\)个操作,每次操作会把数组长度 ...

  9. 【暴力模拟】UVA 1594 - Ducci Sequence

    想麻烦了.这题真的那么水啊..直接暴力模拟,1000次(看了网上的200次就能A)后判断是否全为0,否则就是LOOP: #include <iostream> #include <s ...

随机推荐

  1. 我们可以从英特尔® SPMD 程序编译器中学到什么?

    英特尔® SPMD 程序编译器俗称为“ISPC”,它流畅地展示了 CPU 多核 SIMD 语言.GPU 计算语言.数据并行 C++ 扩展和嵌入式应用或领域特定计算语言的重要未来发展方向.具体而言,本文 ...

  2. 【并行计算-CUDA开发】GPGPU OpenCL/CUDA 高性能编程的10大注意事项

    GPGPU OpenCL/CUDA 高性能编程的10大注意事项 1.展开循环 如果提前知道了循环的次数,可以进行循环展开,这样省去了循环条件的比较次数.但是同时也不能使得kernel代码太大. 循环展 ...

  3. CSS - Animate动画

    下载地址:https://daneden.github.io/animate.css/ 关键CSS样式:animate.css 引入CSS样式 <link rel="styleshee ...

  4. Android MVC MVP MVVM (一)

    示例效果 一共三个控件,EditText,Button,TextView 成功显示账号信息,查询失败显示错误信息. <?xml version="1.0" encoding= ...

  5. 关于MYSQL安装踩的坑

    前提:本人装的版本是mysql-8.0.18-winx64,win10系统,如果你安装的是其他版本的MYSQL,语法会跟下面有些许区别: 一,安装 https://dev.mysql.com/down ...

  6. Vue常见问题集中

    a.VScode保持vue语法高亮的方式: 1.安装插件:vetur.打开VScode,Ctrl + P 然后输入 ext install vetur 然后回车点安装即可. 2.在 VSCode中使用 ...

  7. centos git clone 报错 fatal: HTTP request failed 解决办法

    git clone报错提示 git clone https://github.com/xxxx.git Initialized empty Git repository in /root/xxxx/. ...

  8. Base64encoder干什么用的

    https://baike.baidu.com/item/base64/8545775?fr=aladdin BASE64加密算法.用来给字符串加密的.已经不安全了. 一直以来Base64的加密解密都 ...

  9. 【LOJ】#3086. 「GXOI / GZOI2019」逼死强迫症

    LOJ#3086. 「GXOI / GZOI2019」逼死强迫症 这个就是设状态为\(S,j\)表示轮廓线为\(S\),然后用的1×1个数为j 列出矩阵转移 这样会算重两个边相邻的,只要算出斐波那契数 ...

  10. django form组件 cookies,session

    django form组件 渲染标签  就是组件里面的字段在前端展示叫做渲染标签 校验数据  用户输入的数据提交给后端组件叫做校验数据 forms组件中定义的字段都是必须传值的(required=Tr ...