zoukankan      html  css  js  c++  java
  • 省选模拟33 题解

    A. 盗梦空间

    考虑首先构建一棵虚树,然后跑一遍多源点最短路,求出每个虚树上的点到达最近的关键点的距离。

    分类讨论最终的答案 $u$ 的出现位置。

    1.出现在虚树节点的一个满足子树不含虚树节点的儿子子树中。

    一个很好的性质是我们只关注最大值。

    所以考虑对每个节点维护一个 multiset ,表示这个节点的每个儿子子树中最大的深度。

    每次构建完虚树后,去掉每个满足子树含关键点的儿子的贡献,访问 multiset 中的最大值更新答案即可。

    2.出现在两个相邻的虚树节点的路径上的点的子树中。

    考虑一些简单的情况,设 $x$ 为虚树上的儿子节点, $f$ 为父亲节点, $dis$ 表示最短路数组。

    (1) 如果有 $dis_x=dis_f + dep_x - dep_f$,那么 $dis_u=dis_f + dist(u,f)$。

      因为 $u$ 在 $f$ 的子树中,那么 $dist(u,f)=dep_x-dep_f$ ,要维护的是一个点去除一个儿子贡献的最大 $dep_{son}$ 值。

    (2) 如果有 $dis_f=dis_x+dep_x-dep_f$,那么 $dis_u=dis_x+dist(x,u)$。

      其中 $dist(u,x)=dep_u+dep_x-2*dep_{lca}$,所以要维护的是一个点去除一个儿子贡献的最大的 $dep_{son}-2*dep_{x}$ 值。

    如果不满足这个性质,那么我们可以找到一个分界点,满足分界点的两侧分别满足这两条性质,然后用这样的做法处理。

    比较难搞的是如何处理去除一个点贡献的值,一个简单的想法是树剖,然后维护去除重儿子贡献,对于跳轻边特判。

    一个很套路的容易维护的做法是,对于每个点维护他的父亲节点删掉这个点贡献之后的值,这样的话直接倍增就完事了。

    B. 爱乐之城

    似乎是dy讲课原题。

    这种与子集 $gcd$ 相关的题,套路都是枚举 $gcd$ ,然后算方案数。

    首先定义题中的函数。

    $v(n)=sum limits_{i=1}^n sum limits_{j=1}^n [gcd(i,j)==1]*i*j$

    $h(n)=sum limits_{i=1}^n sum limits_{j=1}^n mu(i*j)$

    直接推式子。

    $ans=sum limits_{T in U} h(gcd(T)) prod_{i in T}v_{a_i}$ 

    $=sum limits_{d=1}^m h(d)sum limits_{T in U}[gcd(T)==d]prod_{i in T}v_{a_i}$

    这里设 $f(x)$ 表示 $gcd$ 为 $x$ 的倍数的贡献和。

    那么有

    $ans=sum limits_{d=1}^m h(d) sum limits_{d|k}mu(k/d)f(k)$
    $=sum limits_{k=1}^m f(k) sum_{d|k}h(d)mu(k/d)$

    设 $g(n)=sum_{d|n} mu(d) h(n/d)$,那么有 $ans=sum limits_{d=1}^m f(d)g(d)$

    因为单次操作只涉及约数个数个 $f$ 的修改,问题只剩下如何求这一堆函数。

    考虑 $f(x)$ 实际上就对应着每个 $x$ 的倍数,有选与不选两种状态,所以 $f(x)=prod_{x|a_i} (v_{a_i}+1)$。

    至于 $v,h$ 函数,简单的用反演推一推式子也可知每次 $n leftarrow n+1$ 的变化量只有约数个数个,所以暴力的复杂度就是 $n ln(n)$ 的。

    C. 星际穿越

    swap(稳定点,不稳定点);

    $r=1$ 的部分分的做法是考虑 $i$ 在 $[1,i]$ 中的排名,然后直接进行 dp 就完事了。

    设 $m=lfloor frac{n-1}{k} floor$ ,即稳定点的个数。

    一个合法的方案,对应着 $m+1$ 段上升序列组成的排列,但是对于每个稳定点与它下一个点的取值是下降的。

    考虑写个容斥。

    设 $f_x$ 表示恰好有 $x$ 个稳定点变成了不稳定点的方案数,$g_x$ 表示至少有 $x$ 个稳定点变成了不稳定点的方案数。

    那么有 $f_0=sum limits_{i=0}^{n} g_i(-1)^i$。

    为了求出 $g$ 数组,考虑一个 dp。

    $dp_{i,j}$表示最后考虑的上升序列的结尾是 $i*k$ ,其中至多有 $j$ 个稳定点,也就是至少有 $i-j$ 个稳定点变成了不稳定点的方案数。

    然后发现这个东西没办法算。但是如果我们知道了每个上升序列的长度 $a_i$,那么这个方案数显然是 $dfrac{n!}{prod a_i!}$。

    所以只要给从 $t$ 到 $i$ 的转移系数设为 $frac{1}{((i-t)*k)!}$ 即可。

    那么有一个显然的基于加法的转移。

    然后观察我们最终要求的答案,发现并不关心具体的 $j$ 的取值,而只关心 $m-j$ 的奇偶性,所以给这个 dp 的转移乘个 $-1$ 的系数就完事了。

    然后发现这个式子是个卷积式,所以推一下式子,整个多项式求逆就好了。

  • 相关阅读:
    扩展json序列化datatime类型数据
    用select实现socket的IO多路复用
    Python单例模式
    Django(信号相关)
    将字符串按固定长度分隔成子串
    Android Handler介绍
    Android activity生命周期
    Java 启动线程的方式
    java线程中的sleep和wait区别
    JAVA 统计字符串中中文,英文,数字,空格的个数
  • 原文地址:https://www.cnblogs.com/skyh/p/12378198.html
Copyright © 2011-2022 走看看