NOIP 模拟赛:2024-11-23

假算法轻取 96pts。

T1:

给定一个\(n\)个结点\(m\)条边的简单无向图,结点编号\(1\sim n\)。你需要构造一个结点编号的排列\(v_1,v_2,\cdots,v_n\),满足

  • \(v_1=1\)
  • \(1< i < n\)至多一个\(i\)满足要求:点对\((v_i,v_{i+1})\)\((v_i,v_{i-1})\)中,一对之间有边直接相连,另一对没有。即对排列中非两端的结点,至多一个和排列中的两侧邻点中恰一个有边直接连接。
    请输出一个满足条件的排列。

"有 \(n\) 个人戴了黑白帽子,每人不知道他的帽子是什么色的,怎么排成黑白分明的队伍?"

让每个人插入到当前序列的黑白交界处即可。

本题一样,让每个结点判断与交界处是否有边来决定去左边还是右边。

T2:

数轴上有 \(n\)个有编号的点,其中在时刻\(t=0\)\(i\)号位于\(x_i\) ,并具有初速度\(v_i\in \{1,-1\}\)(每单位时间的坐标变化)。保证初始位置各不相同。

之后所有点开始运动,如果在时刻\(t\),编号为\(x,y\)的两个点位置重合,且\(v_x=1,v_y=-1\),则碰撞在了一起,这时记录一个碰撞事件\((t,x,y)\),并令\(v_x,v_y\)值互换。如果同时出现多个碰撞事件,可以任意顺序各自独立的结算。

可以发现会出现的碰撞事件\((t,x,y)\)是有限的,请找出字典序排序后的第\(l\sim r\)个事件的\(x,y\),保证存在\(r\)个事件。

\(\dagger\) 多元组\((t,x,y)\)的字典序指先按第一个元素\(t\)从小到大排序,\(t\)相同的按\(x\)从小到大,\(x\)也相同的按\(y\)从小到大。

经典转化:碰撞并不是回头了,而是都继续往前走。

先把所有点按坐标排序。二分 + 双指针可以求出字典序 \(l\sim r\) 的事件所属的时间区间 \([tl,tr]\)

容易发现碰撞对象只可能是相邻两个球。同时 \(i,i+1\) 的第一次碰撞时间等于 \(\le i\) 第一颗右球和 \(\ge i+1\) 的第一颗左球相遇的时间(就是碰撞继续走),第二次碰撞时间是 \(\le i\) 的第二颗右球和 \(\ge i\) 的第二颗左球 ……

我们要找到(第 \(i\) 颗左球,第 \(i\) 颗右球)这些对里,发生时间在 \([tl,tr]\) 里的。

可以预处理 \(lst[i],nxt[i]\) 表示 \(i\) 的上一颗右球、下一颗左球。可以暴力向左右跳。复杂度平方。

因为 \(>tr\) 可以直接 break,瓶颈在于经过了很多发生时间 \(<tl\) 的碰撞。

如何快速找到第一次发生时间 \(\ge tl\) 的碰撞?使用 ST 表加速即可。

坑点:最终可能有开头的几个时间字典序 \(<l\),因为二分可能会留下一点。

T3:

求构造满足如下条件的\(n\)长度整数序列\(a_1,a_2,\cdots,a_n\)的方案数

  • 所有整数的取值范围为\(1\sim m\)
  • \(1\le i < n\),以下两个条件至少一个成立
    • \(a_i\le a_{i+1}\)
    • \((a_i\mod a_{i+1}) > 0\)

答案对998244353取模。两个方案不同,当且仅当存在至少一个位置,使两个序列中该位置的数不相等。
\(n,m\le 10^5\)

妙题。对容斥集合直接 DP。

注意到不满足的条件很苛刻。如果 \(a_i,a_{i+1}\) 是不满足的,必须 \(a_{i+1}\)\(a_i\) 的真因数。而连续的真因数 \(\log n\) 次就变成 \(1\)
因此可以求出 \(c[i][j]\) 为:长度 \(i\) 的序列以 \(j\) 结尾,任意相邻位置不合法的方案数。\(i\le 20\) 可以递推。令 \(sc[i]=\sum c[i][]\)

既然不合法的情况这么少见,可以考虑容斥。怎么容?平时是 "至少 \(0\) 个不满足" - "至少 \(1\) 个不满足" + "至少 \(2\) 个不满足" - ……,容易发现偶数加奇数减。

我们直接 \(dp[i][0/1]\) 表示填前 \(i\) 个数,使得有偶数/奇数个位置不满足的方案数。

如何转移?枚举 \(i\sim i-j\) 是一段连续不合法段,根据上面的观察有 \(j\le 20\)

此时就已经有了 \(j\) 个不合法,方案数是 \(sc[j]\),如果要贡献到 \(dp[i][0]\) 里,后面要有 \(j\bmod 2\) 的位置不满足;否则需要 \(1-j\bmod 2\) 的位置不满足。

dp[i][0] += sc[j + 1] * dp[i - j - 1][j % 2] % MOD;
dp[i][0] %= MOD;
dp[i][1] += sc[j + 1] * dp[i - j - 1][1 - j % 2] % MOD;
dp[i][1] %= MOD;

复杂度 \(O(m\log m+n\log m)\)

posted @ 2024-11-28 14:46  FLY_lai  阅读(25)  评论(0)    收藏  举报