UOJ Logo Picks的博客

博客

NOIp2014 Day2 民间题解

2014-11-09 13:57:51 By Picks

萌萌哒pyx来放题解啦。

第三题由于我是考后才想出来的,所以并没有实际测试,并且可能的解法很多,只是挑了一个更NOIp级别的做法来讲。

T1

考你会不会编程

T2

关键就是怎么样找到可能出现在路径上的点。

那么存在直接或间接地路径到终点,即为将所有边反向后,存在从终点到它的路径。

故只需要反向跑一边遍历,就知道哪些点是存在路径到终点的。

这样,再把所有边扫一遍,就可以知道 $i$ 号点是否可以出现在答案路径上。

由于边权均为1,剩下的只要把可以出现在答案路径上的点BFS一遍就可以了。

T3

解法很多,挑了一个解法。考场上我没有想出来……出了考场才会的。

首先,由于 $a_i$ 很大,联想到CTSC的因式分解那题(其实完全不用这么联想……),我们可以考虑在模意义下来检测。

这么做的正确性,在于几乎不会有不合法的点出现在解当中。不妨取一个 $10^9$ 级别的素数 $P$,那么由于将$10^6$个数带进去,而且可以近似地将答案看做随机数,那么出现一个$0$的概率为$\frac{m}{P}$,就几乎是千分之一了,故我们有$99\%$的可能性在总共10个测试点中不会出现这种情况。

这样,我们以此将$[1,m]$在多项式内求值,利用秦九韶算法可以在$n\times m$次long long乘法,$n \times m$次long long加法,$n \times m$次long long取模中将求值结果算出来。这样就可以获得70分。

但是我亲测这样,极限数据需要1.6s左右。许多大神们就开始用很多高大上的方法将这$m$个数中一些不可能的数去掉,而我试图求导来解方程结果失败了,这里不赘述。

那么,由于我们需要求的是$[1,m]$里所有正整数的答案,假设我们将答案求了出来,考虑将答案差分。

由差分的定理,$n$次多项式的值,差分$n+1$次之后,所剩的值全为0.这个定理比较好证明,这里不叙述。

我们的做法就是,先求出$1 \sim n+1$的$n$次差分的结果,我们可以知道,第$n+1$次差分的结果均为0,为了还原出$m$个数,我们在第$n+1$次差分之后的结果中,填充$m-n$个$0$,然后再还原回来即可。

假设$m>>n$,这样做的话,只需要$n \times m$次在模意义下的int加法即可完成。模意义下的int加法也可以在1次int加法、1次int大小比较与至多1次int减法内完成。这样就可以在1s内通过。

评论

yangff
orz
zerotrac
orz
wyh2000
@vfleaking
TKD
orz
yangff
我来为@Picks 补充一个喜闻乐见的栗子吧. 首先picks干的事情就是...依然是随机素数取mod验证,这些都没有什么特别的地方. 但是他用差分优化了多项式多点求值...的常数. 假如我们有一个函数$f(x)\, = \, 5x^3 \, + \, 3x^2 \, + \, 4x \, + \, 2$. 也就是$n \, = \, 3$啦~ 我们要求它x = 1..4之间的值.. 那就是 14 62 176 386 没错吧. 然后我们不断差分它, 最后我们得到了这样一张表: $\Delta0. f(x)$ 14 62 176 386 $\Delta^1. f(x)$ 48 114 210 336 $\Delta^2. f(x)$ 66 96 126 156 $\Delta^3. f(x)$ 30 30 30 30 $\Delta^4. f(x)$ 0 0 0 0 会发现他在经过$3(n)$次差分之后就变成常数, $4(n \, + \, 1)$次就变成$0$了. 辣么, 如果我说我要求$f(x)$经过$n \, + \, 1$次差分的结果, 也就都是$0$了.. 让$f[i][j]$表示上面那样的表的第$i$行第$j$列.. 于是推回第$0$行,假装第$1$列是已知的, 就是算$f[i][j] \, = \, f[i + 1][j] + f[i][j - 1]$这就是简单的递推.. (根据差分的定义...-或者观察得到-) 最后, 我们只要记得先算$f(1) \, \sim \, f(n)$, 就可以根据差分的定义算出$n$次差分后的$f(1)$(也就是$f[x][1]$)了.. 复杂度没有变化但是所有的乘法变加法, 简直吊炸天. 这次公示应该没错了...!!!
Picks
@yangff你说得很对。
ccc000111
@Picks跪烂……

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。