河南省队胡扯第一场解题报告

     不提早完成任务的报应就是这样……昨天晚上熬夜赶题面捏数据,结果早上起来发现各类漏洞,最后两题还没时间捏数据了,算是完全失败吧= =|||html

     先把题解写出来,下午再慢慢捏数据好了。
算法

 A

     第一题大概意思是维护一个集合,要求实现两种操做:添加一个元素 和 删去其中较大的一半(注意是下取整)。最后还要求可以线性地输出(虽然排序后再输出没有被卡掉……)。
数组

     算法一是直接用一棵平衡树维护,由于每一个元素只可能被删除一次,因此直接暴力删除就能够。
ide

     然而平衡树常数比较大(虽然我已经没有时间去造针对平衡树的数据了……),能够考虑用一个最大堆实现,删除时直接依次弹出就能够了。
idea

     我为正解准备的数据范围彷佛也不怎么合理,只有10^7……其实这个算法是在《算法导论》摊还分析一节中的习题,咱们只须要维护一个无序数列,实现一个$O(|S|)$的删除操做,而每次插入的时候直接将元素附加在数组末尾,就能够在关于操做数呈线性的时间内完成全部操做了。这个一样能够经过“每一个元素只会被删除一次”来证实——咱们能够将每次删除操做须要的时间附加在删除的那些元素对应的插入操做上,因为每次删除的元素个数也是$O(|S|)$,很明显全部删除操做附加在插入操做上的时间是常数级别的。
spa

     对于无序数列的删除操做能够在《算法导论》上的“顺序统计”一节找到。具体地,咱们能够经过相似快速排序的随机算法在线性的指望时间内求出须要删除的最小的元素,将比这个元素小的元素所有移动到数组的前半部分就能够了。code

 

 1 #include 
 2 #include 
 3 
 4  const  int maxn =  10000003;
 5 typedef  long  long LL;
 6 
 7  int A[maxn], *it = A, N;
 8  bool exist[maxn];
 9 
10  int main(){
11 #ifdef DEBUG
12     freopen( " test.txt "" r ", stdin);
13  #endif
14      int *i, M, *t, mid, a, x;
15     unsigned rnd, C;
16     scanf( " %d%d%u%d%u ", &N, &M, &rnd, &a, &C);
17     x = a;
18      while(M--){
19         rnd += (rnd <<  2) +  1;
20          if(rnd & C)*(it++) = x, x = (LL)x * a % N;
21          else{
22             t = A + (it - A +  1) /  2;
23             std::nth_element(A, t, it);mid = *t;
24              for(i = A;i < t;++i) if(*i >= mid)std::swap(*i, *(--it));
25             it = t;
26         }
27     }
28     printf( " %d\n "int(it - A));
29      for(i = A;i < it;++i)exist[*i] =  true;
30      for( int j =  1;j <= N;++j) if(exist[j])printf( " %d  ", j);
31     puts( "");
32      return  0;
33 }
View Code

B

     这题实际上是我把一个idea强行套在了一个经典算法上……因此数据范围出得有点牵强,很是抱歉……
htm

     第一层数据范围是强行留给只会倍增LCA的同窗的(好比一两个个月前的我)。
blog

     第二层数据,因为询问次数比较大(不过我猜我仍是卡不掉倍增……),能够先预处理出dfs序列,构造出ST表来实现$O(1)$查询。
排序

     第三层数据……嗯……说出来大家不要打我啊!= = 咱们来看数据中的N,都符合$3 * 2^i$的形式,因此此中必有蹊跷!观察那个“强制在线”的递推式,u_i = X^{\frac{N}{3} * Ans_{i-1} + k} * i \mod Nv_i = Y^{\frac{N}{3} * Ans_{i-1} + k} * i \mod N,能够发现$\frac{N}{3}$刚好是$\phi(N)$的表达式。那么递推式就变成了这样……

$u_i = X^{\phi(N) * Ans_{i-1}} * X^k * i \mod N$,或$u_i = X^k * i \mod N$。那么咱们就能够用Tarjan LCA离线作了……虽然数据范围很怪异,可是……领会精神,领会精神……

C

     我思考了很久的idea竟被出成了这个鬼样子……= =仍是数据范围的问题,看来不先写std真是不能乱定数据范围啊= =

     算法一:$$F_i = 1 (i = 0 \mod M \lor i < M);$$

                $$F_i = F_{i-1} + F_{i-M}(otherwise)$$

直接递推,不说了;

     算法二:算法一 + 高精度.(其实我实在不想加上这一层数据……)

     算法三:不难发现,从M开始,递推式的选择是以M为周期的。尝试把从0开始的数列中的元素每M个一行铺成矩阵,那么递推式就能够写成这样:

$$F_{i,j} = 1 (i = 0 \lor j = 0)$$

$$F_{i,j} = F_{i-1,j} + F_{i,j-1}$$

     发现递推式很熟悉?没错这个数列其实就是组合数……具体来讲是$F_{i,j} = \tbinom{i}{i+j} = \frac{(i+j)!}{i! j!}$ 用这里介绍的阶乘质因数分解 求组合数就能够了。

相关文章
相关标签/搜索