「模拟赛」多校 A 层联训 9

A. 排列最小生成树 (pmst)

大家都没签上的签到

调参调到 110 能过?!但赛时用 set 这个大常数选手存的边,挂了个 log,所以跑不动大样例。

正解:

发现只按把编号相邻的点连边构成一条链,此时所有边的长度都 \(\le n\),所以无论如何我们都能保证最小生成树每条边的边权 \(\le n\)

那么我们只把边权 \(\le n\) 的边连上即可。边权 \(\le n\) 需要满足 \(abs(i-j)\)\(abs(p_i-p_j)\) 至少有一个 \(\le \sqrt n\)。所以每一个点建上 \(2\times \sqrt n\) 条边即可。

边权最多只有 \(n\),所以开个 vector 数组 \(v_i\) 存边权为 \(i\) 的所有边,这样避免排序的 log 复杂度。

B. 卡牌游戏 (cardgame)

签到

\(lcm\)\(n\)\(m\) 的最小公倍数,\(gcd\)\(n\)\(m\) 的最大公因数,显然 \(lcm\) 轮时正好为一个循环。

而这前 \(lcm\) 轮内保证有每两个人最多比一次。

\(n=k_1\times gcd\)\(m=k_2\times gcd\),所以在一次循环中 \(a_i\)\(b_j\) 比较时一定有 \(i\% gcd=j \% gcd\),并且对于一个 \(i\) 会对应所有的 \(j\ (if\ j\%gcd=i\%gcd)\),所以把 1~n 中所有模 \(gcd\) 余数相同的存一起,1~m 中所有模 \(gcd\) 余数相同的存一起。对于所有的 \(i\in [1,n]\),计算 1~m 中 \(i\% mod\) 的那个桶里有多少小于自己的,等于自己的,大于自己的就好了。

共有 \(\lfloor \frac {n\times m} {lcm} \rfloor\) 次循环,求出一次循环 A 赢的次数、B 赢的次数,乘上循环次数就好了。

对于 \(n\times m \% lcm\) 的那部分,暴力模拟就好。

C. 比特跳跃 (jump)

二进制运算性质

发现其实是一题三做。

  • \(and\) 部分

    发现大部分数都可以做到答案为 0,只有在 \(n\) 的二进制表示全为 1 的时候特殊,这个时候除了 \(n\) 之外的为 0,把与 \(n\) 相关的边建上跑最短路求出的 \(dis_n\) 为 n 的答案;

  • \(xor\) 部分

    将异或运算看成是每一位上相加但不进位,所以每次改变二进制表示下的一位再连边连向原数就好了

  • \(or\) 部分

    或的数越多,权值就越大,所以一个数只由 1 或者自己二进制下 1 的子集表示的数转移过来较优。

    先把 1 连向每个点和那 \(m\) 条边跑一边最短路,然后对于每个数用它二进制下 1 的子集表示的数的权值更新自己,同样每次只改变二进制的一位。

    把当前每个数的权值作为边权存进 Dij 的堆里,再跑一遍最短路。

posted @ 2024-10-20 10:31  Aqr_Rn  阅读(47)  评论(2编辑  收藏  举报