二中省选模拟d2t3记录

给你一个 \(n\times n\) 的矩阵 \(a\),每个位置有一个数或者 \(-1\),你要选择一些位置,满足:

  • 每行每列都有且仅有一个被选中的位置。
  • 不能选 \(-1\) 所在的位置。

记你选的数的和为 \(S\),对于每个 \(i=0,1,\cdots,m-1\),询问是否存在一种合法方案使得 \(S \equiv i \pmod m\)

\[n,m\le 100,-1\le a_{i,j}\le m \]


首先发现这个东西长得很像积和式,只是题目中的运算是求和。

因此我们可以考虑将数放到指数上,这样就可以直接套积和式,我们考虑一个多项式的形式。

\[f(x)=\sum_{p}\prod_{i=1}^nx^{a_{i,p_i}} \]

(其中 \(p\) 是一个长为 \(n\) 的排列)

那么我们只需要在最后检查 \(f(x)\bmod x^m-1\) 的对应次项的系数是否为 \(0\) 即可得知答案。

然而众所周知地,积和式无法在多项式时间内计算,但是我们知道,行列式与积和式长得十分相似:

\[f(x)=\sum_p(-1)^{f(p)}\prod_{i=1}^nx^{a_{i,p_i}} \]

(其中 \(f(p)\) 表示排列 \(p\) 的逆序对数)

但是如果我们直接套行列式,可能出现一个问题,就是负系数的项把正系数的项抵消了。

解决方法就是我们给每个位置赋一个随机的权值。

\[f(x)=\sum_p(-1)^{f(p)}\prod_{i=1}^nc_{i,p_i}x^{a_{i,p_i}} \]

\(c\) 是随机出来的权值)

这样就可以有效减少错误率。

不幸的是,当我们分析时间复杂度时会发现时间复杂度是 \(n^3\times (nm)^2=O(n^7)\) 的。

边乘边取模可以将时间复杂度降到 \(O(n^5)\),但仍然无法通过。

我们考虑优化掉多项式。

(下文记 \(m\) 次单位根的 \(i\) 次方为 \(w_i\)

我们会注意到,单位根 \(w_i\)\(m\) 次方 \((w_i)^m\) 总是等于 \(1\)

因此假如我们将 \(w_i\) 代入 \(f(x)\),就相当于自动对 \(x^m-1\) 取模。

所以我们将每一个 \(m\) 次单位根代入 \(f(x)\),最后直接插值,就可以得到原来的多项式。

这个题到这里就做完了,时间复杂度 \(O(n^4)\)

但是如果直接使用浮点数存复数,不仅精度容易爆,还跑得慢容易被卡场。

所以我们考虑将整个多项式 \(f(x)\) 对一个大素数 \(p\) 取模,只需要在本地提前打好素数和对应的原根表即可。


另外,mxz在赛时使用模拟退火通过了此题,让我们 /bx 他。 /bx/bx/bx

具体方法是以 \(-1\) 的个数为指标,在最小化它的过程中记录途中的和的出现情况。

为什么我的模拟退火没过过题,这不公平

posted @ 2025-02-23 17:50  CuteNess  阅读(16)  评论(0)    收藏  举报