zoukankan      html  css  js  c++  java
  • 一些省选题

    BJOI2019

    loj #3089. 「BJOI2019」奥术神杖

    看见乘法的贡献就应该考虑取对数,之后变成(frac{1}{c}sum ln v_i).

    求这个式子的最值可以考虑分数规划,即二分(mid)后check(frac{1}{c}sum ln v_i>mid)

    整理后得(sum(ln v_i-mid)>0),故可以将每个串的长度记作(ln v_i-mid),之后就是一个经典的在AC自动机上dp的过程了,注意记录转移以输出方案。

    code

    loj #3090. 「BJOI2019」勘破神机

    先考虑(m=2)的case,发现填满一个(2 imes n)的方格的方案就是(fib_{n+1}),其中(fib_i)表示斐波那契数列的第(i)项。

    答案(=frac{1}{r-l+1}sum_{i=l+1}^{r+1}dbinom{fib_i}{k}),和这个题是一样的。

    接下来考虑(m=3)的case。依然是先算填满一个(3 imes n)的方阵的方案数(g_n),由于(n)必然为偶数,于是可以考虑其为(3 imes (n imes 2))的方案数。递推的话可以考虑上一个不经过分界线的矩阵大小,若其为(2)则有(3)种,否则则为(2)种。故可得到递推式(g_n=sum_{i=1}^{n-2}2g_i+3g_{n-1}).将(g_{n+1})(g_n)做差可得(g_{n+1}=4g_n-g_{n-1}),边界条件(g_0=1,g_1=3).利用特征根法解得通项式如下:

    [g_n=frac{3+sqrt 3}{6}(2+sqrt 3)^n+frac{3-sqrt 3}{6}(2-sqrt 3)^n ]

    剩下的和(m=2)的一致。

    code

    loj #3092. 「BJOI2019」排兵布阵

    分组背包即可,跑得飞快。

    code

    loj #3093. 「BJOI2019」光线

    (f_i)为1号镜子入射的光线从(i)号镜子向下射出的量,(g_i)表示1号镜子入射的光线从(i)号镜子向上反射的量,转移有:

    [f_i=a_if_{i-1}+b_ig_{i+1}\ g_i=b_if_{i-1}+a_ig_{i+1} ]

    注意由于(g_{n+1}=0),所以有(f_n=a_nf_{n-1},g_n=b_nf_{n-1}).

    (X_i=frac{f_i}{f_{i-1}},Y_i=frac{g_i}{f_{i-1}}),那么转移式可以写成:

    [X_i=a_i+b_iY_{i+1}X_i\ Y_i=a_i+a_iY_{i+1}X_i ]

    由于(X_n,Y_n)已知,所以可以倒推求出(X_i),再求出(f_n)即可。

    当然还有一个做法是不显式的设出(X,Y),注意到由于(f_n,g_n)分别可以被(f_{n-1},g_{n-1})表示出来,再往前推既可以发现(f_i,g_i)分别可以被(f_{i-1},g_{i-1})表示。最后由(f_0=1)再往后乘一遍系数即可。

    code

    loj #3094. 「BJOI2019」删数

    对于一个序列(a)首先考虑怎样才能使它被一次删干净。由于长度为(n),所以(a)中必有元素(n),假设有(k_1)个。为了能继续删,序列(a)中必有元素(n-k_1),假设有(k_2)个,以此类推。

    用一个形象化的比喻来解释最后的结论:记(b_i=sum_{j=1}^n [a_j=i]),考虑一根数轴上有一些柱子,点(i)的柱子高度为(b_i),那么最少修改次数等于将([1,n])中的所有柱子向右推倒后未被覆盖的整点个数。

    考虑用线段树维护这个过程,每个节点维护当前区间的最小值,最小值出现次数和答案,只有在最小值为0时它的次数才会被记入答案中。对于修改,单点修改直接做,整体加减的话可以记录原点(0)的位置,每次直接移动(0)的位置,再修改由此离开或进入([1,n])的柱子的贡献,此时需要将下标整体加上一个较大的数。

    code

    BJOI2018

    loj #2491. 「BJOI2018」求和

    注意到(k)很小,于是可以对所有(k)预处理出每个点深度的(k)次幂,再用树链剖分查询即可。

    code

    loj #2492. 「BJOI2018」二进制

    结论五分钟,实现两小时

    假设某个区间有(m)(0)(n)(1),那么问题等价于从集合({2^0,2^1,cdots,2^{n+m-1}})中选出(n)个数使其和为3的倍数。

    (n=1)时显然不成立。(n)为偶数时注意到(3|2^{2k}+2^{2k+1})(kin N)均成立,故此时一定可行。(n)(>1)的奇数时,我们可以先拿(3)个奇数出来选(2^0,2^2,2^4),剩下的数再和(n)为偶数的方案一样选即可。注意到此时我们需要两个(0)(2^1)(2^3),那么当前区间不合法的条件就很明显了:

    • (n=1)

    • (n=2k+1,m<2(kin N_{+}))

    注意到两个条件是或的关系,于是我们可以强制第一个条件满足(mgeq 2).

    考虑用线段树维护这个东西,记(dl/r[i][j])表示子区间包含当前区间左/右端点,且子区间的(0)(i)个,子区间内(1)的个数(mod 2)(j)的子区间数量(它被用来统计第二个条件的贡献)。(fl/r[i][j])表示子区间包含当前区间的左/右端点,且子区间内有(0/1/geq 2)(0),(1)个1的子区间数(用来处理第一个条件的贡献),(c0/c1)表示区间内(0/1)的个数,(l0/r0)表示从左端点/右端点出发的极长(0)段的长度(这两个是方便维护(dl/r,fl/r)的)。具体的pushup由于细节繁多建议直接看代码。

    code

    loj #2512. 「BJOI2018」链上二次求和

    (s_i)(a_i)的前缀和,(ss_i)(s_i)的前缀和。二次求和肯定要写两次前缀和啊

    对于一个询问([l,r]),把它的答案写出来:

    [egin{aligned} &sum_{i=l}^rsum_{j=i}^n s_j-s_{j-i}\ =& sum_{i=l}^r(sum_{j=i}^n s_j-sum_{j=0}^{n-i} s_j) \ =& sum_{i=1}^r(ss_n-ss_{i-1}-ss_{n-i})\ =&(r-l+1)ss_n-sum_{i=l-1}^{r-1}ss_i-sum_{i=n-r}^{n-l}ss_i end{aligned} ]

    考虑如何动态维护(ss_i),这样的话对每次询问可以直接查([1,n],[l-1,r-1],[n-r,n-l]),然后减一减得到答案。

    对于一个修改((l,r,v)),对(forall iin[l,r]),它的影响是(frac{(i-l+1)(i-l+2)}{2}v); 而对(forall iin(r,n]),记(len=r-l+1),则贡献为((frac{len(len+1)}{2}+len(i-r))v).

    注意到上面的所有贡献都可以看成是关于(i)的二次函数,于是可以在build的时候预处理出(i^0,i^1,i^2),每次修改直接传入各次项前的系数即可。具体实现可参考代码。

    code

    loj #2513. 「BJOI2018」治疗之雨

    连续两年高妙消元?

    (f_i)表示当前血量为(i),变成(0)的期望次数。则有:

    [f_i=1+sum_{j=1}^{min(i+1,n)} A_{i,j}f_j ]

    其中(A_{i,j})为血量由(i)变为(j)的概率,经过简单的分类讨论可以得到

    [A_{i,j}= egin{cases} B_{i-j} & i=n,jleq n\ 0 & i=n,j=n+1\ frac{1}{m+1}B_0 & i<n,j=i+1\ frac{1}{m+1}B_{x+1-y}+frac{m}{m+1}B_{x-y} &i<n,j eq i+1 end{cases} ]

    其中(B_i)表示在(k)次操作中恰好选到某个特定点(i)次的概率,则有:

    [ B_i=frac{1}{(m+1)^k}{kchoose i}m^{k-i} ]

    (f),由于(i)可能由比它大的数转移过来,所以我们需要高斯消元,但是显然时间限制不允许我们这么做。

    (f_i)的转移变形后得到:

    [f_{i+1}=frac{f_i-1-sum_{j=1}^jA_{i,j}f_j}{A_{i,i+1}}(i<n) ]

    于是(f_i)可以由(f_{i-1})得到,我们将(f_1)看做主元,可以表示出(f_{2...n}).

    但是对(f_n)的转移,由于不存在(f_{n+1})所以上面的变形不成立,但是我们直接利用这个转移建立起(f_n)(f_1)的第二个等量关系,之后解方程得到(f_1)。注意特判一下(m=0)(k=0)的情况。

    code

    SDOI2019

    loj #3110. 「SDOI2019」快速查询

    维护一些全局tag:加法add,乘法mul,赋值all以及最近的一次全局赋值时间lstall. 再对有单点赋值的位置记录一下上一次赋的值和时间。单点询问的时候比较一下全局时间和单点时间的先后。询问和的话在修改的时候顺便维护一下即可。

    code

    loj #3111. 「SDOI2019」染色

    一眼有一个没分的dp思路:记(f_{i,j,k})表示前(i)列已经填完,第(i)列的颜色为(j,k)的方案数。

    考虑压缩状态,记(g_{i,j})表示前(i)列,第(i)列新填的颜色是(j)的方案数。当第(i)列被填满时,考虑记录下面位置的颜色。那么问题变成出列一列都没有颜色的情况。注意到我们可以将这样的连续的几列放在一起处理,并且这些列的情况只与开头和结尾的两个非全零列有关,大致有以下几种:

    (1.egin{bmatrix} a & 0 & cdots & 0 & b\ c & 0 & cdots & 0 & d \ end{bmatrix})

    (2.egin{bmatrix} a & 0 & cdots & 0 & b\ b & 0 & cdots & 0 & d \ end{bmatrix})
    (egin{bmatrix} a & 0 & cdots & 0 & c\ c & 0 & cdots & 0 & d \ end{bmatrix})(两者等价)

    (3.egin{bmatrix} a & 0 & cdots & 0 & a\ c & 0 & cdots & 0 & d \ end{bmatrix})
    (egin{bmatrix} a & 0 & cdots & 0 & b\ c & 0 & cdots & 0 & c \ end{bmatrix})(两者等价)

    (4.egin{bmatrix} a & 0 & cdots & 0 & a\ b & 0 & cdots & 0 & b \ end{bmatrix})

    (5.egin{bmatrix} a & 0 & cdots & 0 & b\ b & 0 & cdots & 0 & a \ end{bmatrix})

    (f_{i,j})表示有(i)(0),其中首尾两列的情况为(j)的方案数(注意这个状态中我们只确定了首尾两列的相等情况,而没有确定具体的数是什么)

    预处理出(f),之后对每一对极长连续的全零列转移,暴力(O(nc))的转移可以得到96pts. 代码有亿点细节。

    写完96pts的代码后发现我们每次对(g)的操作和上一题是相同的,于是可以把前一题的代码蒯过来再改一下。这里笔者由于笔者比较懒只有96pts的代码。

    code(96pts)

    loj #3112. 「SDOI2019」世界地图

    对于询问([l,r]),考虑将([1,l-1])([r+1,n])的MST合并.即需要预处理所有前缀和后缀的MST。

    这里只考虑前缀的MST,后缀的是类似情况。一个比较显然的思路是由([1,l-1])推出([1,l])。考虑一条新的边((u,v,w))在何时会替代原MST中的边:在原MST中(u,v)连通且两点间路径的最大权值(>w).

    ([1.l])中第一列点和最后一列点为关键点,(pre_l)为随着(l)的增大可能会被删去的边,根据kruskal的过程不难发现加入边((u,v))等价于将它们的祖先连起来,所以(pre_l)的边的端点可以看成是关键点。所以每次向后拓展时只需要考虑(pre_l)与新加的边。

    再考虑合并,发现我们依然可以只关注关键点的连边,于是可以将(pre_{l-1})(suf_{r+1})如上面一样的合并起来,具体合并过程可见代码。

    code

    loj #3113. 「SDOI2019」热闹的聚会与尴尬的聚会

    注意到第二问这个求独立集是个经典的NPC问题,所以一个直观的想法是让(q)尽量小,也就是要让(p)尽量大。

    那么有一个这样的贪心思路:每次删去当前图中度数最小的点(记作这一次删除的源点),并删去其相邻的点。每次删点时删去的点的度数最大值即为(p),所有删去的点在一起则构成第二问的独立集。

    考虑这样得到的独立集的大小,由于每个被删去的源点在被删去时的度数(leq p),所以每次删去的点的总数(leq p+1),所以(qgeq lfloorfrac{n}{p+1} floor),合法性得证

    code

    联合省选2020

    以下按照个人认为的难度顺序排序

    Day1

    loj#3305. 「联合省选 2020 B」卡牌游戏

    (s_i=sum_{j=1}^i a_j),由于每个(s_i)至多产生1次贡献,故答案(=sum_{i=2}^nmax(s_i,0)).

    code

    loj#3306. 「联合省选 2020 B」消息传递

    建出点分树,对每个点记录下它在点分树上的祖先到这个点的距离(这个可以在建立点分树的时候通过dfs当前分治重心所管理的子树得到),同时在点分树上对每个点维护其子树中的点到这个点的距离的桶。询问时直接在点分树上暴力跳父亲,然后对着桶查一下即可。

    code

    loj#3300. 「联合省选 2020 A」组合数问题

    主要思路是将后面的(sum x^kdbinom{n}{k})分离出来,再用二项式定理合起来即可。

    [egin{aligned} &sum_{k=0}^nf(k)x^kdbinom{n}{k}\ =&sum_{i=0}^ma_isum_{k=0}^nk^ix^kdbinom{n}{k}\ =&sum_{i=0}^ma_isum_{k=0}^nx^kdbinom{n}{k}sum_{j=0}^iS(i,j)k^{underline{j}}\ =&sum_{i=0}^ma_isum_{j=0}^iS(i,j)sum_{k=0}^nx^kfrac{n!}{k!(n-k)!}frac{k!}{(k-j)!}\ =&sum_{i=0}^ma_isum_{j=0}^iS(i,j)n^{underline{j}}sum_{k=0}^nx^kdbinom{n-j}{k-j}\ =&sum_{i=0}^ma_isum_{j=0}^iS(i,j)n^{underline{j}}sum_{k=0}^{n-j}x^{k+j}dbinom{n-j}{k}\ =&sum_{i=0}^ma_isum_{j=0}^iS(i,j)n^{underline{j}}x^j(x+1)^{n-j} end{aligned} ]

    其中(S(i,j))表示第二类斯特林数。

    预处理一堆东西之后就可以(O(m^2))了。

    code

    loj#3299. 「联合省选 2020 A | B」冰火战士

    记冰系战士和火系战士在温度(i)时上场战士的能量和分别为(S_{0i},S_{1i}),那么问题就是求最大的(i)使(min(S_{0i},S_{1i}))的最大。

    (j)为最小的(i)使(S_{0i}> S_{1i}),那么在(iin[1,j-1])时,(min(S_{0i},S_{1i})=S_{0i}),此时(j-1)是最优解。在(iin[j,n])时,(min(S_{0i},S_{1i})=S_{1i}),为了让这个值最大,需要找到一个最大的(p)使(S_{1p}=S_{1j}).

    这两个操作都可以在线段树上二分实现,时间复杂度为(O(nlog n))

    code

  • 相关阅读:
    内网或无域名服务器集成微信公众号接口
    记录一次重新学习SetInternal和SetTimeout
    SQLServer日志过大导致还原失败的解决方案
    批量修改SQLServer数据库表字段属性
    收缩SQLServer数据库解决日志占用空间过大(2008R2以上版本)
    SAP GUI安装出现ocx错误提示的解决办法
    .NetCore自动转换枚举类显示自定义中文名称
    EFCore-脚手架Scaffold发生Build Failed问题的终极解决
    .NetCore自定义WebAPI返回Json的格式大小写的三种方式
    存储过程模糊搜索,按匹配率排序初探
  • 原文地址:https://www.cnblogs.com/encodetalker/p/13068762.html
Copyright © 2011-2022 走看看