一定要分析清楚复杂度再打!!!窝再也不要花2h20min用暴力对拍暴力啦!!!

雨露均沾(滑稽),尽量避免孤注一掷。先把暴力分拿全再回来刚正解。

即使剩下的时间不多了也优先考虑认真读题+打暴力而非乱搞(当然是在乱搞得分没有保证的情况下)。

明明是最近几套题中最难的却改的最顺利?大概是因为也就这次考场上认真思考了吧。

A.简单的区间

考场启发式合并复杂度写假了……和暴力没区别QAQ

首先考虑题目中柿子的具体含义:对于一段区间,以最大值所在处为界(不含)劈成两半,如果这两半的和是K的倍数就符合条件。

那这道题就和之前那道english十分相像了,考虑单调栈预处理每个数作为最大值控制的区间,因为这些区间构成一棵完全二叉树所以可以启发式合并。

由于要计算符合条件区间的个数,所以维护一个桶,下标为$\% K$的余数。如果两个数$\% K$同余那么他们的差一定是K的倍数,所以用前缀和实现桶的更新与查询。

那么具体怎么启发式合并呢?

首先比较左右儿子区间长度,首先把短区间递归下去处理,然后把桶清空(因为待会统计答案的时候不能算它自己这一段的)。接着递归处理长区间,之后桶里已经有了长区间的信息了,所以可以暴力枚举短区间,把 与枚举到的点的前缀和 同余的 区间 个数计入答案。当然因为不计入最大值本身,所以枚举计算贡献时如果是左区间要加上最大值,右区间则减去最大值。

细节很多,而且左右儿子作为短区间时考虑的东西不太一样……主要就是左区间要用前缀和涉及到$sum[l-1]$的问题。另外处理完一个区间要把短区间啥也没选的情况减去。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<stack>
  5. #include<vector>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N=3e5+5;
  9. int read()
  10. {
  11. int x=0,f=1;char ch=getchar();
  12. while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
  13. while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
  14. return x*f;
  15. }
  16. int n,K,L[N],R[N],ls[N],rs[N];
  17. ll a[N],ans,bu[1000005],sum[N];
  18. stack<int> q;
  19. void work(int i)
  20. {
  21. int l=L[i],r=R[i];
  22. if(l==r){bu[sum[i]%K]++;return ;}
  23. if(r-i<i-l)
  24. {
  25. if(rs[i])work(rs[i]);
  26. for(int j=i;j<=r;j++)
  27. bu[sum[j]%K]=0;
  28. if(ls[i])work(ls[i]);
  29. bu[sum[l-1]%K]++;
  30. for(int j=i;j<=r;j++)
  31. ans+=bu[(sum[j]-a[i])%K];
  32. for(int j=i;j<=r;j++)
  33. bu[sum[j]%K]++;
  34. bu[sum[l-1]%K]--;
  35. }
  36. else
  37. {
  38. if(ls[i])work(ls[i]);
  39. for(int j=l;j<=i;j++)
  40. bu[sum[j]%K]=0;
  41. if(rs[i])work(rs[i]);
  42. bu[sum[i]%K]++;
  43. for(int j=l;j<=i;j++)
  44. ans+=bu[(sum[j-1]+a[i])%K];
  45. for(int j=l;j<=i-1;j++)
  46. bu[sum[j]%K]++;
  47. }
  48. ans--;
  49. }
  50.  
  51. int main()
  52. {
  53. /*freopen("dt.in","r",stdin);
  54. freopen("my.out","w",stdout);*/
  55. n=read();K=read();
  56. for(int i=1;i<=n;i++)
  57. a[i]=read(),sum[i]=sum[i-1]+a[i];
  58. for(int i=1;i<=n;i++)
  59. {
  60. while(!q.empty()&&a[q.top()]<=a[i])q.pop();
  61. if(!q.empty())L[i]=q.top()+1,rs[q.top()]=i;
  62. else L[i]=1;
  63. q.push(i);
  64. }
  65. while(!q.empty())q.pop();
  66. for(int i=n;i;i--)
  67. {
  68. while(!q.empty()&&a[q.top()]<a[i])q.pop();
  69. if(!q.empty())R[i]=q.top()-1,ls[q.top()]=i;
  70. else R[i]=n;
  71. q.push(i);
  72. }
  73. for(int i=1;i<=n;i++)
  74. if(L[i]==1&&R[i]==n){work(i);break;}
  75. /*for(int i=1;i<=n;i++)
  76. cout<<i<<' '<<L[i]<<' '<<R[i]<<' '<<ls[i]<<' '<<rs[i]<<endl;*/
  77.  
  78. cout<<ans<<endl;
  79. return 0;
  80. }

B.简单的玄学

竟然是个古典概型……还以为要容斥或者递推什么的……

“至少两个变量相同”显然与“没有任何变量相同”互斥,所以只要求出后者后用1减一下即可。

那么这个答案显然为$\frac{A_{2^n}^m}{2^{nm}}$

化简一下,得到

$\frac{\prod_{i=2^n-m+1}^{2^n-1}}{2^{n(m-1)}}$

可以发现,如果$m>mod$,那么分子一定会被模成0,所以不用考虑m过大的情况。

接下来的问题是约分。分母中的质因子只有2,所以需要求出分子中2的个数。根据$2^k-i$中2的个数等于$i$中2的个数,可以把问题转化为求$(m-1)!$中2的个数。可以$O(log\ m)$求。

接下来逆元搞一下就得到了答案。$1-\frac{a}{b}=\frac{b-a}{b}$。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cmath>
  5. using namespace std;
  6. typedef long long ll;
  7. const ll mod=1e6+3,inv=500002;
  8. ll n,m;
  9. ll qpow(ll a,ll b)
  10. {
  11. ll res=1;
  12. while(b)
  13. {
  14. if(b&1)res=res*a%mod;
  15. a=a*a%mod;
  16. b>>=1;
  17. }
  18. return res;
  19. }
  20. int main()
  21. {
  22. scanf("%lld%lld",&n,&m);
  23. if(log2(m)>n){puts("1 1");return 0;}
  24. ll mi=qpow(2,n),mot=qpow(mi,m),res=1;
  25. for(ll i=0;i<m&&res;i++)
  26. res=res*(mi-i)%mod;
  27. ll cnt2=n;
  28. for(ll i=2;i<m;i<<=1)cnt2+=(m-1)/i;
  29. mot*=qpow(inv,cnt2)%mod,mot%=mod;
  30. res*=qpow(inv,cnt2)%mod,res%=mod;
  31. printf("%lld %lld\n",(mot-res+mod)%mod,mot);
  32. return 0;
  33. }

C.简单的填数

最不擅长这种乱搞题了……

定义u为使$a[n]$最大的每个位置填数方案,d为使$a[n]$最小的每个位置填数方案。

那么显然u尽量2个进1,d尽量5个进1。

然后根据已经填的数调整u和d的值和左端点位置,中间特判掉无解情况。

这样扫一遍就可以得到最大的$a[n]$。

然后倒着扫一遍构造方案即可。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. const int N=2e5+5;
  6. int read()
  7. {
  8. int x=0,f=1;char ch=getchar();
  9. while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
  10. while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
  11. return x*f;
  12. }
  13. int n,a[N],num[N];
  14. struct node
  15. {
  16. int x,pos;
  17. }
  18. u[N],d[N];
  19. int main()
  20. {
  21. n=read();
  22. for(int i=1;i<=n;i++)
  23. a[i]=read();
  24. if(a[1]!=1&&a[1]!=0){puts("-1");return 0;}
  25. u[1].pos=u[1].x=d[1].pos=d[1].x=1;
  26. for(int i=2;i<=n;i++)
  27. {
  28. d[i]=d[i-1];u[i]=u[i-1];
  29. d[i].pos++;u[i].pos++;
  30. if(u[i].pos>2)u[i].x++,u[i].pos=1;
  31. if(d[i].pos>5)d[i].x++,d[i].pos=1;
  32. if(!a[i])continue;
  33. if(u[i].x>a[i])u[i]=(node){a[i],2};
  34. else if(u[i].x==a[i])u[i].pos=min(u[i].pos,2);
  35. if(d[i].x<a[i])d[i]=(node){a[i],1};
  36. if(u[i].x<a[i]||d[i].x>a[i]){puts("-1");return 0;}
  37. }
  38. if(u[n].pos==1)u[n].x--,u[n].pos=u[n-1].pos+1;
  39. if(u[n].x<d[n].x){puts("-1");return 0;}
  40. a[n]=u[n].x;
  41. printf("%d\n",a[n]);
  42. num[a[n]]=1;
  43. for(int i=n-1;i;i--)
  44. {
  45. if(!a[i])
  46. {
  47. int val=min(a[i+1],u[i].x);
  48. if(num[val]==5)val--;
  49. a[i]=val;
  50. }
  51. num[a[i]]++;
  52. }
  53. for(int i=1;i<=n;i++)
  54. printf("%d ",a[i]);
  55. putchar('\n');
  56. return 0;
  57. }
  58. /*
  59. 7
  60. 0 1 0 0 0 3 0
  61. */

[NOIP模拟测试37]反思+题解的更多相关文章

  1. [NOIP模拟测试34]反思+题解

    不要陷入思维定势,如果长时间没有突破就要考虑更改大方向. 不要把简单问题复杂化. 做完的题就先放下,不管能拿多少分.不能过一段时间就回来调一下. $Solutions:$ A.次芝麻 因为$n+m$始 ...

  2. [NOIP模拟测试32]反思+题解

    又考挂了QAQ 总rank直接滑出前20 晚上考试脑子还算比较清醒,可惜都用来xjb乱想错误思路了. T1一眼推柿子,然而并没有头绪所以先码了个暴力.然后…… 一个垃圾暴力我调了1h,大概解决了两位数 ...

  3. 2019.8.1 NOIP模拟测试11 反思总结

    延迟了一天来补一个反思总结 急匆匆赶回来考试,我们这边大家的状态都稍微有一点差,不过最后的成绩总体来看好像还不错XD 其实这次拿分的大都是暴力[?],除了某些专注于某道题的人以及远程爆踩我们的某学车神 ...

  4. 2019.7.29 NOIP模拟测试10 反思总结【T2补全】

    这次意外考得不错…但是并没有太多厉害的地方,因为我只是打满了暴力[还没去推T3] 第一题折腾了一个小时,看了看时间先去写第二题了.第二题尝试了半天还是只写了三十分的暴力,然后看到第三题是期望,本能排斥 ...

  5. 2019.8.14 NOIP模拟测试21 反思总结

    模拟测试20的还没改完先咕着 各种细节问题=错失190pts T1大约三分钟搞出了式子,迅速码完,T2写了一半的时候怕最后被卡评测滚去交了,然后右端点没有初始化为n…但是这样还有80pts,而我后来还 ...

  6. 2019.8.9 NOIP模拟测试15 反思总结

    日常爆炸,考得一次比一次差XD 可能还是被身体拖慢了学习的进度吧,虽然按理来说没有影响.大家听的我也听过,大家学的我也没有缺勤多少次. 那么果然还是能力问题吗……? 虽然不愿意承认,但显然就是这样.对 ...

  7. 2019.8.3 NOIP模拟测试12 反思总结【P3938 斐波那契,P3939 数颜色,P3940 分组】

    [题解在下面] 早上5:50,Gekoo同学来到机房并表态:“打暴力,打暴力就对了,打出来我就赢了.” 我:深以为然. (这是个伏笔) 据说hzoi的人还差两次考试[现在是一次了]就要重新分配机房,不 ...

  8. 2019.8.12 NOIP模拟测试18 反思总结

    写个博客总是符合要求的对吧 回来以后第一次悄悄参加考试,昨天全程围观… 然后喜提爆炸120分wwwwwwwww T1用了全机房最慢的写法,导致改掉死循环T掉的一个点以后还是死活过不了最后一个点.T2全 ...

  9. 2019.8.10 NOIP模拟测试16 反思总结【基本更新完毕忽视咕咕咕】

    一如既往先放代码,我还没开始改… 改完T1滚过来了,先把T1T2的题解写了[颓博客啊] 今天下午就要走了,没想到还有送行的饯别礼,真是欣喜万分[并没有] 早上刚码完前面的总结,带着不怎么有希望的心情开 ...

随机推荐

  1. Python基础教程(014)--缩进错误

    前言 学会编写格式 内容 print(“HelloWorld”) print(“HelloWorld”) ----缩进错误 print(“HelloWorld”) 错误信息: IndentationE ...

  2. RHEL/CentOS通用性能优化、安全配置参考

    RHEL/CentOS通用性能优化.安全配置参考 本文的配置参数是笔者在实际生产环境中反复实践总结的结果,完全适用绝大多数通用的高负载.安全性要求的网络服务器环境.故可以放心使用. 若有异议,欢迎联系 ...

  3. 2-prometheus各组件安装

    相关下载: https://prometheus.io/download/https://github.com/prometheus/ 相关文档 https://songjiayang.gitbook ...

  4. [CSP-S模拟测试]:序列(主席树)

    题目描述 小$A$把自己之前得到的序列展示给了小$B$,不过这一次,他并不要求小$B$模仿他之前的行为.他给了小$B$一些询问,每个询问都是$l\ r\ x$的形式,要求小$B$数出在序列的第$l$个 ...

  5. 【Java架构:持续交付】一篇文章搞掂:持续交付理论

    一.持续集成.持续交付.DevOps概念,关系等 持续集成(Continuous integration/CI) 持续交付(Continuous delivery/CD) 持续部署() 持续 (Con ...

  6. ceph安装问题

    ceph-deploy安装 Yum priorities pluginLoaded plugins: fastestmirror Loaded plugins: fastestmirror, prio ...

  7. Https 代理 sslsocket

    1. 什么是SSLSocket JDK文档指出,SSLSocket扩展Socket并提供使用SSL或TLS协议的安全套接字. 这种套接字是正常的流套接字,但是它们在基础网络传输协议(如TCP)上添加了 ...

  8. wireshark 识别http的标准

    使用route add 本机ip 255.255.255.255 网关ip metric 1 的方式 会使访问本机ip的连接发送到局域网内,这样wireshark就可以抓取到 但有一点需要注意 如果本 ...

  9. Codeforces 1188D Make Equal DP

    题意:给你个序列,你可以给某个数加上2的幂次,问最少多少次可以让所有的数相等. 思路(官方题解):我们先给序列排序,假设bit(c)为c的二进制数中1的个数,假设所有的数最后都成为了x, 显然x &g ...

  10. 十一、结构模式之享元(Flyweight)模式

    什么是享元模式 享元模式是对象的结构模式,是运用共享技术来有效的支持大量细粒度的对象.享元对象能做到共享的关键是区分内蕴状态和外蕴状态.一个内蕴状态是存储在享元对象内部,并且是不会随环境改变而有所不同 ...