Portal -->agc003E

Description

  给你一个数串\(S\),一开始的时候\(S=\{1,2,3,...,n\}\),现在要对其进行\(m\)次操作,每次操作给定一个\(a\),具体方式为将\(S\)重复写很多很多很多次然后取前\(a\)个数作为新的\(S\),问最后得到的\(S\)中\(1\sim n\)每个数的出现次数

  

Solution

  emmm想到了解法但是想用线段树解决原本暴力就可以解决的东西然后就凉了==

  首先手玩一下小规模的数据,记当前\(S\)的长度为\(nowlen\),要变成的新的长度为\(x\),\(cnt[i]\)表示当前数字\(i\)出现的次数,分两种情况讨论一下:

1、如果说\(nowlen<=x\):那么所有的\(cnt[i]\)肯定都要\(*x/nowlen\),然后再加上余数的贡献(这部分比较复杂,先不展开说)

2、如果说\(nowlen>x\):那么会发现我们要先找到之前的某次操作使得那次操作之后\(S\)的长度\(<=x\),然后再回到1中的情况

  

​  也就是说,我们其实只关心长度不下降的操作,所以接下来提到的操作都是以最后一个操作结尾的不下降操作序列(记为\(st[i]\)好了)中的元素

​  现在我们着重思考一下那个余数的问题,考虑余数(记为\(rest\))部分的贡献其实就是\(S\)的前\(rest\)个数,那其实我们要做的就是查询某次操作之后\(S\)的前\(rest\)个数中每个数出现的次数,会发现这个其实就是。。原问题,那所以。。递归求解之类的。。?

​  我们考虑实现一个过程\(solve(x,l)\)表示在第\(x\)次操作之后,\(S\)前\(l\)位中每个数出现的次数(假装返回值是一个数组),记\(cnt[i]\)表示第\(i\)次操作之后\(S\)中每个数字的出现次数(其实就是一个二维数组啦==不过当然只是方便理解这么说,实际实现的时候并不需要开这么一个玩意)那么大概可以写出来一个\(solve(x,l)=l/st[x-1]*cnt[x-1]+solve(x-1,l\%st[x-1])\)

  然后接下来就是一个比较重要的经典性质:一个数每次模不大于它的数,总共只能模\(log\)次

  (没错反正我当时弱智了没有反应过来==)

  所以至多递归\(log\)层(当\(l=0\)的时候自然就直接返回了嘛)

  所以我们可以考虑暴力一点来处理这个东西(数据结构什么的是没有前途的qwq比如说一开始想了一个可持久化线段树==显然空间爆炸)

  

​  注意到根据上面那条。。递归式,我们可以知道\(cnt[i]\)可以被表示为至多\(log\)个带个系数的\(cnt[j](j<i)\)每次再加上一些不需要递归处理的余数的贡献(也就是当余数\(<=st[1]\)的时候,此时不需要再递归处理而是可以直接得到,因为肯定是对从\(1\)开始的连续的某一段的数字有贡献,或者更加笼统一点就是一个前缀)的和,所以我们考虑维护一个\(addtag\),\(\sum\limits_{i=1}^x addtag[i]\)表示处理到当前,数\(x\)的不需要递归处理的余数贡献,再维护一个\(multag[i]\)表示,用\(cnt[i]\)来表示\(cnt[m]\)(也就是最后的\(cnt\))时,前面需要乘的系数(其实如果再直白一点。。可以说\(addtag\)其实就相当于一个零头,当然这个说法不严谨),那么由于最开始的\(cnt\)是知道的(都是\(1\)),所以最后数字\(x\)的答案(如果不为\(0\)的话)就应该是\(multag[1]*1+\sum\limits_{i=1}^xaddtag[i]\)

​  最后就是实现问题了,其实就是正常每次把商乘上去就好了好像也没有什么特别要说的。。

  

​  mark:(貌似依旧是没有什么建设性的东西。。)把未知的转化成已知的。。?比如说就是把系数推出来然后用最开始的cnt来表示最后的cnt

​  mark:一个数每次模不大于它的数,总共只能模\(log\)次

  

​  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+10;
ll a[N];
ll ans[N],st[N],addtag[N],multag[N];
int n,m;
ll nowlen;
void prework(){
st[0]=0; a[0]=n;
for (int i=0;i<=m;++i){
while (st[0]&&st[st[0]]>a[i]) --st[0];
st[++st[0]]=a[i];
}
}
int get_pos(ll x,int r){
int l=1,mid,ret=r;
while (l<=r){
mid=l+r>>1;
if (st[mid]<=x) ret=mid,l=mid+1;
else r=mid-1;
}
return ret;
}
void solve(ll k,ll rest,int ed){
if (!rest) return;
if (rest<=st[1]){
addtag[1]+=k; addtag[rest+1]-=k;
return;
}
int pre=get_pos(rest,ed);
multag[pre]+=k*(rest/st[pre]);
solve(k,rest%st[pre],pre-1);
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
ll rest,tmp,x;
scanf("%d%d",&n,&m);
nowlen=n;
for (int i=1;i<=m;++i) scanf("%lld",a+i);
prework();
multag[st[0]]=1;
for (int i=st[0];i>=2;--i){
tmp=st[i]/st[i-1];
rest=st[i]%st[i-1];
multag[i-1]+=multag[i]*tmp;
solve(multag[i],rest,i-1);
}
for (int i=1;i<=st[1];++i){
addtag[i]+=addtag[i-1];
printf("%lld\n",addtag[i]+multag[1]);
}
for (int i=st[1]+1;i<=n;++i) printf("0\n");
}

最新文章

  1. Servlet规范简介——web框架是如何注入到Servlet中的
  2. 用GSON解析Json格式数据
  3. 通过lua获取nginx的内置变量,通过这些变量做些逻辑的处理
  4. zmq 学习笔记
  5. 如何设置 Windows 开机启动项
  6. windows内核窥探
  7. 菜鸟学开店—最简收银POS系统
  8. SetThreadAffinityMask设置线程亲缘性
  9. 转: object 和embed 标签播放flash
  10. IIS 7关闭应用程序池自动回收设置
  11. PAT (Basic Level) Practise (中文) 1017. A除以B (20)
  12. cocos 动画系统
  13. 【笔记】Nginx热更新相关知识
  14. 在公网上的Linux,我的一些配置分享
  15. MySQL的随笔
  16. Xilinx原语学习之时钟资源相关原语
  17. Android开源系列:仿网易Tab分类排序控件实现
  18. 非常完善的Log4net详细说明(转)
  19. 使用react封装评论组件
  20. Python自定义Module中__init__.py文件介绍

热门文章

  1. 准备正式开始学习C++,先发点牢骚
  2. 禁用 Python GC,Instagram 性能提升10%
  3. 从零开始的Python爬虫速成指南
  4. Python 深浅复制
  5. “Hello World!团队”Beta发布—视频链接+文案+美工
  6. MySql 8 命令
  7. erlang中检查内存泄露
  8. playbook详解—YAML格式的文本
  9. 3dContactPointAnnotationTool开发日志(三十)
  10. CCF——门禁系统201412-1