Codeforces Round #232 (Div. 1)(A,B,C,D)

来源:互联网 发布:淘宝联盟需要交钱吗 编辑:程序博客网 时间:2024/05/22 00:09

比赛链接: http://codeforces.com/contest/396

代码链接: https://github.com/9974/Codeforces/tree/master/232div1


A

分解质因数, 对于每个质数单独考虑,假设质数2的指数为m, 那么我们要做的就是求   把m个2分配给n个数 的情况数

用高中的挡板法得  C[m+n-1][n],  每个质数是相互独立的,所以都乘起来就好了。


B

u和v的变化情况为  (2,3)  , (3,5)  (5, 7)  ........        在完整的一段中  对为(u,v)  有v-u个,把这些合并一下  我们可以化简成1/u  - 1/v。 考虑完整的一段,   

对于 n在完整段中   找到 所在的对(u,v) , 那么最后答案为 1/2 - 1/v  , 对于不完整的, 完整的一段先处理一下,剩下来的几个数单独处理。


C

线段树:首先,很明显的是树转链, 对于-i*k的那部分更新,把它转化一下,看成是以1节点(根)下来的更改,那么每个点的值必然会增加减少dep[v]*k(v为询问的根节点),我们不妨把它跟x的那部分并起来加上去, 用一个线段树维护A区间和,  同时转化以后,我们再用一个线段树B维护k的区间和,    最后v所在的A.val减去v所在的B.val*dep[v]就是答案


树状数组: 这里由于 询问是单点的,所以也可以用2个树状数组维护一下前缀和,   对于区间[l, r] + v    我们可以通过add(l,v)  add(r+1, -v) 这两个操作完成更新,  询问的时候询问当前点的前缀和就可以了。


D

根据数位来实现枚举到了所有的字典序,做过数位dp的应该很懂。

枚举每个位k。我们可以分3种情况来计算收益(即答案)

1. 前面k-1数字与所给的序列相等,  第k位不相等。统计 第k位产生的收益 

假设前面比a[k]小的数有cnt个,那么   对于k位   我们可以有  a[k]-1-cnt个选择。k位可以选剩下来的数的   第一小,第二小........ 第    a[k]-1-cnt小的数,  所带来的收益分别是     0*(n-k)!,1*(n-k) ..... n-k*(n-k)!       总收益为  (n-k)!*(n-k-1)*(n-k)/2

2.前面k-1数字与所给的序列相等,  第k位不相等。 统计第k位以后的全排列产生的收益 

对于1---n的n个数的全排列, 考虑每个点对(a,b)在全排列中的 先后顺序 , 产生收益的情况是总情况的一半,一共有n*(n-1)/2个点对    总收益为n*(n-1)/2 *n! / 2  =  n*(n-1)*n! / 4

3.前面k-1个位部分前缀相同 。        前k-1部分相同个的位跟k之后(包括k)的位产生的 收益

当放到第i位后就能知道后面比它小的数有多少个(无论后面怎么排),个数为w, 那么i位置之后的计算都要算上w*枚举的情况数, 所以我们可以用一个变量pre来维护 第k位之前  在情况数为1的时候的第1,2....k-1位带来的总体收益。


前缀和可以用树状数组维护

5 0