P6523 「Wdoi-1」加密通信 题解

CSDN同步

原题链接

简要题意:

给定一个数列 \(a_1 , a_2 \cdots a_{n-1}\),求 任意一个满足以下条件的长度为 \(n\) 的质数数列 \(\text{ans}\)

\[\text{ans}_i \times \text{ans}_{i+1} = a_i \]

本题是某洛谷公开赛 \(T1\),有一定思维难度。

前记

本人 \(193ms\) 的代码截止 \(\text{2020.5.5 12:00}\) 排名第一,效率最高。 如果不开火车头优化就屈居第三了 (实际上估计也 不太 会有人能超过它了,除非是变态卡常)

下面的 \(m\) 指的是:

\[m = \max_{i=1}^n a_i \]

并且,各算法对应的数据范围没有下限是因为不存在特殊情况,特此说明。

算法一

对于 \(20 \%\) 的数据,\(n \leq 5\)\(m \leq 10\).

显然我们可以发现,如果确定了 \(p_1\),就可以递推出整个数列。

由于 \(p_1\) 只受到 \(a_1\) 的限制(即 \(p_1 | a_1\)),所以我们枚举 \(a_1\)质因子 作为 \(p_1\),然后递推判断即可。

时间复杂度:\(O(Tn \sqrt{m})\)

解释:\(T\) 组数据,每组数据枚举因数是 \(O(\sqrt{m})\) 的时间,递推是 \(O(n)\) 的时间,而判断素数我们可以打表(反正 \(20\) 以内的素数也不多),\(O(1)\) 判断即可。

实际得分:\(20pts\) ~ \(40pts\).(下面会有说明)

Link 代码

注:上述代码并没有预处理素数表。(实际上浪费 \(\sqrt{M}\) 的时间也不会有什么问题)

算法二

对于 \(40 \%\) 的数据,\(m \leq 10^{12}\).

这个部分分没什么用,是用来给选手乱搞的。

出题人的官方题解中说:

(看得不太清楚可以放大看)

实际上这样理论上是无法通过 \(n \leq 10^5\) , $T \leq 5 $, \(m \leq 10^{12}\) 这样庞大的数据。

简单计算一下:

你可以欧拉筛出 \(\sqrt{m} = 10^6\) 以内的素数表,共 \(78498\) 个,估算为 \(8 \times 10^4\) 个。

你在这 \(8 \times 10^4\) 个中枚举因数,然后 \(O(n)\) 验证。

时间复杂度:\(O(Tn \times 8 \times 10^4)\).

简单估计:\(O(5 \times 10^5 \times 8 \times 10^4 = 40 \times 10^9 = 4 \times 10^{10})\).

所以理论上,如果跑满时间复杂度是根本无法通过的,也无法分析该程序具体的常数是多少。

可能出题人的数据有点弱,导致每次 \(O(n)\) 根本跑不满,枚举到半路就被剪枝了吧。

所以按照算法一的思路,卡一卡常数就可以得到 \(40pts\).

时间复杂度:\(O(Tn \sqrt{m})\).

实际得分:\(20pts\) ~ \(40pts\).

算法三

对于 \(70 \%\) 的数据,\(a_i \not = a_{i+1}\).

暂时我们想不出,\(a_i \not = a_{i+1}\) 有什么性质。

那么先把得到的 \(n-1\) 个方程组列出来吧:

\[ \begin{cases} p_1 \times p_2 = a_1 \\ p_2 \times p_3 = a_2 \\ \\ \vdots \\ p_{n-1} \times p_n = a_{n-1} \\ \end{cases} \]

只看前两个方程,我们可以得到的是:

\[p_2 | \gcd(a_1 , a_2) \]

同理,我们可以得到:

\[p_x | \gcd(a_{x-1} , a_x) (1 < x < n) \]

然而,因为 题目保证没有上限的限制就有解,所以,\(\gcd(a_{x-1} , a_x)\) 只存在一个质因子。

只存在一个质因子,又 \(\because a_i \not = a_{i-1} (1 < i < n)\)\(\therefore p_i = \gcd(a_{i-1},a_i) (1 < i < n)\).

我们不需要算那么多个 \(\gcd\),只需要算出 \(p_2\),就可以递推得到整个序列!

时间复杂度:\(O(Tn \log m)\).(只保证 \(70 \%\) 的数据答案正确,不保证 \(100 \%\) 的数据答案都正确)

实际得分:\(70pts\).

算法四

对于 \(100 \%\) 的数据,\(T \leq 5\)\(n \leq 10^5\)\(m \leq 10^{18}\).

可以发现,\(O(Tn \log m)\) 完全可以通过本题,但是,对于 \(a_i = a_{i+1}\) 的情况,\(\gcd(a_{i-1} , a_i) = a_i\),根本没有起到一点点降低时间的可能。

但是,我们只需要 求出一个 \(p_i\) 就可以得到整个序列,注意到题目保证:

至少存在一组 \((i,j)\),使得 \(a_i \not = a_j\).

这说明整个序列 不完全一样,也就是说 至少存在一组 \(a_i \not = a_{i+1}\).

那么,我们只需要找到这个位置,求出 \(p_i\),然后往两边递推就可以得到答案。

时间复杂度:\(O(Tn \log m)\).(保证答案正确)

实际得分:\(100pts\).

Link 代码

posted @ 2020-05-05 11:37  bifanwen  阅读(244)  评论(0编辑  收藏  举报