T1

类似于昨天的t3,先用单调栈求出管控区间,然后暴力求解30pts

我没取模还没开longlong,然后就爆0了

正解:

  • 仍然是用单调栈求一下区间,用线段树维护一下余数,对于i所对应的区间\([l_{i},r_{i}]\) ,当然是去枚举离i近的,剩下的用线段树求解,线段树要用动态开点,不然空间会炸。
Code
  1. #include<cstdio>
  2. #define K 1000010
  3. #define MAX 300010
  4. #define re register
  5. #define int long long
  6. namespace OMA
  7. {
  8. int n,k,ans;
  9. int a[MAX],sum[MAX];
  10. int root[K];
  11. int top,L[MAX],R[MAX],sta[MAX];
  12. struct Segmnet_Tree
  13. {
  14. int tot;
  15. struct TREE
  16. {
  17. int res;
  18. int ls,rs;
  19. }st[K*50];
  20. inline void Push_up(int p)
  21. { st[p].res = st[st[p].ls].res+st[st[p].rs].res; }
  22. inline void insert(int &p,int l,int r,int pos)
  23. {
  24. p = (!p)?++tot:p;
  25. if(l==r)
  26. { st[p].res = 1; return ; }
  27. int mid = (l+r)>>1;
  28. if(pos<=mid)
  29. { insert(st[p].ls,l,mid,pos); }
  30. else
  31. { insert(st[p].rs,mid+1,r,pos); }
  32. Push_up(p);
  33. }
  34. inline int query(int p,int l,int r,int lp,int rp)
  35. {
  36. if(l<=lp&&rp<=r)
  37. { return st[p].res; }
  38. int sum = 0,mid = (lp+rp)>>1;
  39. if(l<=mid)
  40. { sum += query(st[p].ls,l,r,lp,mid); }
  41. if(r>mid)
  42. { sum += query(st[p].rs,l,r,mid+1,rp); }
  43. return sum;
  44. }
  45. }Tree;
  46. inline int read()
  47. {
  48. int s=0,w=1; char ch=getchar();
  49. while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
  50. while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
  51. return s*w;
  52. }
  53. inline void STACK()
  54. {
  55. for(re int i=1; i<=n; i++)
  56. {
  57. while(top&&a[sta[top]]<=a[i])
  58. { R[sta[top--]] = i-1; }
  59. L[i] = sta[top]+1;
  60. sta[++top] = i;
  61. }
  62. while(top)
  63. { R[sta[top--]] = n; }
  64. }
  65. signed main()
  66. {
  67. n = read(),k = read();
  68. for(re int i=1; i<=n; i++)
  69. { (sum[i] = sum[i-1]+(a[i] = read())%k) %= k; }
  70. STACK();
  71. for(re int i=1; i<=n; i++)
  72. { a[i] %= k; Tree.insert(root[sum[i]],1,n,i); }
  73. for(re int i=1; i<=n; i++)
  74. {
  75. if(L[i]==R[i])
  76. { continue ; }
  77. if(R[i]-i<i-L[i])
  78. {
  79. for(re int j=i+1; j<=R[i]; j++)
  80. {
  81. if(L[i]-1)
  82. { ans += Tree.query(root[(sum[j]-a[i]+k)%k],L[i]-1,i-1,1,n); }
  83. else
  84. {
  85. int temp = (sum[j]-a[i]+k)%k;
  86. ans += Tree.query(root[temp],L[i],i-1,1,n);
  87. if(!temp)
  88. { ans++; }
  89. }
  90. }
  91. if(L[i]-1)
  92. { ans += Tree.query(root[sum[i-1]],L[i]-1,i-2,1,n); }
  93. else
  94. {
  95. if(i-2)
  96. { ans += Tree.query(root[sum[i-1]],1,i-2,1,n); }
  97. if(!sum[i-1])
  98. { ans++; }
  99. }
  100. }
  101. else
  102. {
  103. for(re int j=L[i]; j<=i-1; j++)
  104. { ans += Tree.query(root[(sum[j-1]+a[i])%k],i,R[i],1,n); }
  105. if(i<R[i])
  106. { ans += Tree.query(root[sum[i]],i+1,R[i],1,n); }
  107. }
  108. }
  109. printf("%lld\n",ans);
  110. return 0;
  111. }
  112. }
  113. signed main()
  114. { return OMA::main();}
  • 也可以用主席树,但我不会。

  • vector做法,用lower_bound,upper_bound,找合法区间的个数。

  • 以及正解

T2

式子很好推,结果被我一顿乱搞+瞎取模取成了10pts。

首先正难则反(来自数学课),可以先求出变量互不相同时的式子

\[ans=\frac{A_{2^{n}}^{m}}{2^{n\times m}}=\frac{\begin{matrix} \prod_{i=2^{n}-m+1}^{2^{n}-1} \end{matrix}}{2^{n\times(m-1)}}
\]

然后我就码了个快速幂,求阶乘逆元gcd,一顿乱搞30pts->10pts

此时,我自己造了几个数据,发现显然不对,于是去想如何改一下。没想出来,交了个10pts。

正解:

推出式子后,考虑约分,发现只能约2及其倍数。所以去找有多少个2。

然后有个定理 \(2^{n}-a\)和\(a\) 这俩东西中,2的个数是相等的,所以找分子中2的个数,就转换成了去找 \((m-1)!\) 中2的个数,这个可以 \(O(logm)\) 求解。

对于\(m>mod\) 此时一定有一个数为mod的倍数,所以分子为0,但答案并非这个,因是%mod意义下的0,所以直接去计算分母就好了。

\(m\le mod\) 的话,直接暴力计算就好了。

Code
  1. #include<cstdio>
  2. #define MAX 1000100
  3. #define re register
  4. #define int long long
  5. namespace OMA
  6. {
  7. int n,m,a,b;
  8. int inv,c,cnt=63;
  9. const int p = 1e6+3;
  10. inline int quickpow(int a,int b)
  11. {
  12. int ans = 1;
  13. while(b)
  14. {
  15. if(b&1)
  16. { ans = ans*a; }
  17. a = a*a;
  18. b >>= 1;
  19. }
  20. return ans;
  21. }
  22. signed main()
  23. {
  24. scanf("%lld%lld",&n,&m);
  25. n %= p-1;
  26. int tmp1 = 1,tmp2 = 0;
  27. while(cnt--)
  28. { tmp1 <<= 1; if(tmp1>=m){ break; } (tmp2 += (m-1)/tmp1) %= p-1; }
  29. c = quickpow(2,n),inv = quickpow(quickpow(2,tmp2),p-2);
  30. b = quickpow(c,(m-1)%(p-1))*inv%p;
  31. if(m<=p)
  32. {
  33. a = inv;
  34. for(re int i=1; i<=m; i++)
  35. { (a *= c-i) %= p; }
  36. a = ((b-a)%p+p)%p;
  37. printf("%lld %lld\n",a,b);
  38. }
  39. else
  40. { printf("%lld %lld\n",b,b); }
  41. return 0;
  42. }
  43. }
  44. signed main()
  45. { return OMA::main(); }

T3

考试的时候写了个f**k大模拟+贪心,还过了自己造的hack数据,结果程序输出全是-1 10pts好成绩

考试做法错误是显然的,比如1 0 0 0 1,我的码会输出-1,因为是从前往后扫,出现次数超过1就换下一个值,顾前不顾后,wa也正常。

正解:

我们可以设二元组(a,b),表示当前位置上的数为a,其连续的长度为b。分别设两个 \(up\)和\(down\),up为能填的最大值,down为最小值,求up应该尽量往上,down相反。

最大值即为 \(up[n].a\),序列倒着就能求出来。具体实现见code。

Code
  1. #include<cstdio>
  2. #define MAX 200010
  3. #define re register
  4. namespace OMA
  5. {
  6. int n,m,cnt[MAX];
  7. int a[MAX],ans[MAX];
  8. struct pair
  9. { int a,b; };
  10. pair up[MAX],down[MAX];
  11. inline int read()
  12. {
  13. int s=0,w=1; char ch=getchar();
  14. while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
  15. while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
  16. return s*w;
  17. }
  18. inline int min(int a,int b)
  19. { return a<b?a:b; }
  20. signed LZk()
  21. {
  22. n = read();
  23. for(re int i=1; i<=n; i++)
  24. { a[i] = read(); }
  25. a[1] = 1;
  26. up[1] = down[1] = (pair){1,1};
  27. for(re int i=2; i<=n; i++)
  28. {
  29. up[i] = (pair){up[i-1].a,up[i-1].b+1};
  30. down[i] = (pair){down[i-1].a,down[i-1].b+1};
  31. if(up[i].b>2)
  32. { up[i] = (pair){up[i].a+1,1}; }
  33. if(down[i].b>5)
  34. { down[i] = (pair){down[i].a+1,1}; }
  35. if(a[i])
  36. {
  37. if(up[i].a>a[i])
  38. { up[i] = (pair){a[i],2}; }
  39. if(down[i].a<a[i])
  40. { down[i] = (pair){a[i],1}; }
  41. if(up[i].a<a[i]||a[i]<down[i].a)
  42. { printf("-1\n"); return 0; }
  43. }
  44. }
  45. if(up[n].b==1)
  46. { up[n] = (pair){up[n-1].a,up[n-1].b+1}; }
  47. printf("%d\n",up[n].a);
  48. a[n] = up[n].a,cnt[up[n].a]++;
  49. for(re int i=n-1; i>=1; i--)
  50. {
  51. if(!a[i])
  52. {
  53. int tmp = min(a[i+1],up[i].a);
  54. if(cnt[tmp]==5)
  55. { tmp--; }
  56. a[i] = tmp;
  57. }
  58. cnt[a[i]]++;
  59. }
  60. for(re int i=1; i<=n; i++)
  61. { printf("%d ",a[i]); }
  62. return 0;
  63. }
  64. }
  65. signed main()
  66. { return OMA::LZk(); }

noip12的更多相关文章

  1. 20210712 noip12

    考场 第一次和 hzoi 联考,成功给 sdfz 丢人 尝试戴耳罩,发现太紧了... 决定改变策略,先用1h看题,想完3题再写. T1 一下想到枚举最大值,单调栈求出每个点能作为最大值的区间,然后以这 ...

随机推荐

  1. buu RSA

    一.分析 下载链接,发现一个公钥的文件(e,n),和一个加密过的文件 二. 公钥文件,里面一堆字母,然后后面百度,才知道需要去解开n,e 指数是e,模数是n(十六进制) 三.再通过n来分解素数,得到p ...

  2. Android 开发学习进程0.32 dwonloadmanager使用

    downloadmanager时Android系统下载器,使用系统下载器可以避免用stream流读入内存可能导致的内存溢出问题.以下为downloadmanager初始化部分.apkurl为下载网络路 ...

  3. Java和C#语法对比(转)

        Java C# 访问修饰符 public 修饰类.接口.变量.方法. 对所有类可见. 修饰类.接口.变量.方法. 对所有类可见.   internal 无. 修饰类.接口.变量.方法. 类,接 ...

  4. Spring boot中相关的注解

    一.相关类中使用的注解 @RestController:REST风格的控制器 @RequestMapping:配置URL和方法之间的映射 @SpringBootApplication:应用程序入口类 ...

  5. docker之构建镜像

    构建Docker镜像有以下两种方法: 使用docker commit命令. 使用docker build命令和 Dockerfile 文件. 在这里并不推荐使用docker commit来构建镜像,而 ...

  6. python使用笔记25--深拷贝、浅拷贝

    1.循环删除list 1 ll = [1,1,32,4,3,2,3,2,4,6,4,5,6,7,8] 2 for i in ll: 3 if i % 2 !=0: 4 ll.remove(i) 5 p ...

  7. redis反向代理docker容器中的rabbit mq服务

    最近做的项目中用到了docker,发现docker容器还真挺好用的,可以统一来管理各种资源,项目. 但是在实际使用中就碰到下面这个问题(下面所有的应用都是在docker中启动的): 通过nginx来反 ...

  8. keeplived+mycat+mysql高可用读写分离水平分表(谁看谁都会)

    一:环境准备: 应用 主机 mysql-master 192.168.205.184 mysql-slave 192.168.205.185 mycat-01,keeplived,jdk 192.16 ...

  9. nacos配置本地多个实例(伪集群)

    在本地配置多个nacos实例(伪集群),一般就是配置多个nacos端口,并启动多个startup.sh脚本.网上一些博客通过修改startup.sh脚本来指定不同nacos端口,比如:./startu ...

  10. Apache atlas liunx环境安装部署手册

    一.        背景 本文使用一台ubuntu虚拟机安装Apache-atlas,使用集成包unzip apache-atlas-2.1.0.zip进行快速安装部署,该集成包高度集成了hadoop ...