y d c 的 题 面 * 2
题解
测试点 1 ~ 3 : 1_998244353
输入:
1 | 1_998244353 |
输出:
1 | 1 (=19^0) |
显然是要求 $19^x$。
但是输出很明显被取模了。你可以直接通过看 功能编号 看出模数是 $998244353$。或者可以用以下的数学推导过程:
由于在输入中,$19^7 = 893871739$ 没爆模数,但是$19^8 = 893871739 \times 19$ 爆了。所以模数肯定是 $19^8 - 13409040 = 16970154001 = 17 \times 998244353$ 的约数且大于 $893871739$,所以模数只可能是 $998244353$
对于测试点 1,$x < 10^5$,所以可以循环求解,时间复杂度 $O(x_{max})$
对于测试点 2,$x$ 在 long long
范围内,考虑快速幂处理,时间复杂度 $O(n \ log \ x)$
对于测试点 3,$x$ 超出了 long long
范围。根据扩展欧拉定理,$a^b \equiv a^{b\text{ mod }\varphi(m) + \varphi(m)} \pmod m$,由于 $998244353$ 是质数,所以 $\varphi(998244353) = 998244352$,所以在输入时将数字对 $998244352$ 取模,然后快速幂求 $a^{b + 998244352}$ 即可。
预计得分:12
代码见下文。
测试点 4:1?
输入:
1 | 1? |
输出:
1 | 1 |
这一次没有模数了,需要我们自己思考。
我们发现输出数字并不大,所以模数肯定也不大,所以我们考虑找到输出中最大的数字,然后从那个数字开始枚举,直至找到答案。
输出中最大的数是 $1145099$,在输出数据的第 3303 行和第 23865 行。
所以我们从 $1145099$ 开始枚举,最终枚举到答案是 $1145141$。
照样扩展欧拉定理一波。
预计得分:19
测试点 5:1?+
输入:
1 | 1?+ |
输出:
1 | ... |
我们发现这一次输出的数字过大,明显无法直接枚举。
所以我们可以考虑测试点 3 的数学计算法。
我们幸运地发现有两组数据十分接近:
1 | 7146| 264708066 |
再找到它们对应的输出:
1 | 7143| 1996649514996338529 |
所以模数一定是 $1996649514996338529 \times 19^2 - 1589589654696467295 = 719200885258981741674$ 的约数。
最后分解下来为 $5211600617818708273$,快速幂处理。注意使用快速乘或者 __int128
来防止爆 long long
。
预计得分:28
测试点 6 ~ 7:1wa_998244353
输入:
1 | 1wa_998244353 |
输出:
1 | 1 |
出现负数,计算过程中肯定爆 long long
了。
我们注意到题目中的一段话:
如果你的程序希望利用
int
的自然溢出的特性,请转换为unsigned
类型运算。例如将a + b
改写为(int) ((unsigned) a + (unsigned) b)
,以避免出现不预期的错误。
所以我们可以运用这个方法。在测试点 6 中,$x \le 10^5$,所以考虑用上面自然溢出的办法模拟求值。
对于测试点 7,数字过大,无法直接模拟,所以考虑求循环节,使用 map
找出循环节,直接求解即可。
预计得分:41
测试点 8 ~ 10:2p
我们先随便观察两组输入输出:
1 | 输入:2 10 输出:pp.p.p... |
首先非常明显的发现,输出是一个区间。其次,我们发现,如果该字符下标是质数,则该字符是 p,否则是 .
所以这是区间求质数题…
对于测试点 8,$L, R \le 10^6$,直接线性筛。
对于测试点 9 和 10,可以对每个数跑一遍 Miller-Rabin
算法。
预计得分:59
测试点 11 ~ 13:2u
首先观察输出,发现只有 +-0 三种符号。
再看编号 2u,基本上就能猜出来这是莫比乌斯函数。
对于测试点 11, $L, R <= 10^6$ ,依旧线性筛解决。
对于剩下的两个测试点,可以打表解决,也可以使用如下的非打表算法:
首先,先筛出 $2$ ~ $10^6$ 之间的质数。然后,对于给定区间里的数,我们先用这些小于 $10^6$ 的质数去进行分解。过程中注意一旦筛到 $n$ 有平方数因子就把 $\mu (n)$ 直接设为 $0$,且计算筛到质数的乘积。
此时,如果用完小于 $10^6$ 的质数进行分解后,筛到的乘积仍然小于原数,只有以下三种情况:
- 剩下这个数是质数。
判断方法: Miller-Rabin 一遍即可。(强调一遍,只要用一个 $2$ 判断就可以了!)
2. 剩下这个数是平方数。判断方法: 将剩下这个数 sqrt 后判断即可。(有些大佬没判这个也 A 了,为了保险我还是判了)
3. 剩下这个数是两个不同的,大于 $10^6$ 的质数之积。
只要上述两个条件均不成立,那这个条件自然成立。可以证明,剩下的数肯定不会是三个及以上大于 $10^6$ 的质数的乘积。
预计得分:79
测试点 14~15:2g
,测试点 16:2g?
看出这三个点需要较强的数论知识,因为如果不知道原根是很难看出来的。
不过只要写过求原根,或者 N 次剩余和 NTT 代码的都应该知道原根。
如果您不会相关知识,您可以看下面的概念:
- 阶:对于两个互质的数 $a,n$,定义 $a$ 模 $n$ 的阶为满足 $a^d \equiv 1 \pmod n$ 的最小正整数 $d$。记作 $\delta _n(a)$。由欧拉定理可知,$\delta _n(a) | \varphi(n)$。
- 原根:如果 $\delta _n(a) = \varphi(n)$,则 $a$ 是模 $n$ 意义下的原根。一般用 $g$ 表示。
- 指标:记作 $\operatorname{ind}_g x$,表示一个数 $x$ 在 $\mod p$ 意义下关于原根 $g$ 的离散对数。
那么,如何求原根呢?
很简单,根据原根的定义,对于模数 $p$ 和一个数 $a$,如果对于任意一个 $\varphi(p)$ 的质因子 $q$,有 $a^{\frac{\varphi(p)}{q}} \equiv 1 \pmod p$。那么 $a$ 就不是 $p$ 的原根。
对于测试点 14,对模数质因子分解,暴力判断即可。
测试点 15 模数发生了变化,直接暴力跑不过去。考虑用指标做。
先找出模数的一个原根 $6$,然后线性扫一遍指标。当一个数的指标与 $\varphi(p)$ 互质时,该数就是 $p$ 的原根,否则不是。
测试点 16 需要自己找模数,这个别的大佬都讲过了,模数是 $1515343657$,用测试点 14 的方法暴力即可。
代码
1 |
|