P8814 [CSP-J 2022] 解密(民间数据)题解

题目传送门

[CSP-J 2022] 解密(民间数据)

题目描述

给定一个正整数 k k k,有 k k k 次询问,每次给定三个正整数 n i , e i , d i n_i, e_i, d_i ni,ei,di,求两个正整数 p i , q i p_i, q_i pi,qi,使 n i = p i × q i n_i = p_i \times q_i ni=pi×qi e i × d i = ( p i − 1 ) ( q i − 1 ) + 1 e_i \times d_i = (p_i - 1)(q_i - 1) + 1 ei×di=(pi1)(qi1)+1

输入格式

第一行一个正整数 k k k,表示有 k k k 次询问。
接下来 k k k 行,第 i i i 行三个正整数 n i , d i , e i n_i, d_i, e_i ni,di,ei

输出格式

输入 k k k 行,每行两个正整数 p i , q i p_i, q_i pi,qi 表示答案。
为使输出统一,你应当保证 p i ≤ q i p_i \leq q_i piqi
如果无解,请输出 NO

样例 #1

样例输入 #1

10
770 77 5
633 1 211
545 1 499
683 3 227
858 3 257
723 37 13
572 26 11
867 17 17
829 3 263
528 4 109

样例输出 #1

2 385
NO
NO
NO
11 78
3 241
2 286
NO
NO
6 88

提示

【样例 #2】
见附件中的 decode/decode2.indecode/decode2.ans
【样例 #3】
见附件中的 decode/decode3.indecode/decode3.ans
【样例 #4】
见附件中的 decode/decode4.indecode/decode4.ans
【数据范围】
以下记 m = n − e × d + 2 m = n - e \times d + 2 m=ne×d+2
保证对于 100 % 100\% 100% 的数据, 1 ≤ k ≤ 10 5 1 \leq k \leq {10}^5 1k105,对于任意的 1 ≤ i ≤ k 1 \leq i \leq k 1ik 1 ≤ n i ≤ 10 18 1 \leq n_i \leq {10}^{18} 1ni1018 1 ≤ e i × d i ≤ 10 18 1 \leq e_i \times d_i \leq {10}^{18} 1ei×di1018
1 ≤ m ≤ 10 9 1 \leq m \leq {10}^9 1m109

测试点编号 k ≤ k \leq k n ≤ n \leq n m ≤ m \leq m特殊性质
1 1 1 1 0 3 10^3 103 1 0 3 10^3 103 1 0 3 10^3 103保证有解
2 2 2 1 0 3 10^3 103 1 0 3 10^3 103 1 0 3 10^3 103
3 3 3 1 0 3 10^3 103 1 0 9 10^9 109 6 × 1 0 4 6\times 10^4 6×104保证有解
4 4 4 1 0 3 10^3 103 1 0 9 10^9 109 6 × 1 0 4 6\times 10^4 6×104
5 5 5 1 0 3 10^3 103 1 0 9 10^9 109 1 0 9 10^9 109保证有解
6 6 6 1 0 3 10^3 103 1 0 9 10^9 109 1 0 9 10^9 109
7 7 7 1 0 5 10^5 105 1 0 18 10^{18} 1018 1 0 9 10^9 109保证若有解则 p = q p=q p=q
8 8 8 1 0 5 10^5 105 1 0 18 10^{18} 1018 1 0 9 10^9 109保证有解
9 9 9 1 0 5 10^5 105 1 0 18 10^{18} 1018 1 0 9 10^9 109
10 10 10 1 0 5 10^5 105 1 0 18 10^{18} 1018 1 0 9 10^9 109

附件

decode.zip 1.74kb

二分方法

俗话说得好,看题先看数据范围。
一开始我没看范围,一看是一道橙题立马打了暴力,然后就…
在这里插入图片描述
由于这道题数据范围很大,只能考虑O(logn)和O(1)的复杂度
要解出这道题,我们先要了解韦达定理
在这里插入图片描述
然后看题目中的两句话:

求两个正整数 p i , q i p_i, q_i pi,qi,使 n i = p i × q i n_i = p_i \times q_i ni=pi×qi e i × d i = ( p i − 1 ) ( q i − 1 ) + 1 e_i \times d_i = (p_i - 1)(q_i - 1) + 1 ei×di=(pi1)(qi1)+1

以下记 m = n − e × d + 2 m = n - e \times d + 2 m=ne×d+2

推导亿下:

m = n − e × d + 2 m = n - e \times d + 2 m=ne×d+2
m = p i × q i − ( p i − 1 ) ( q i − 1 ) + 1 + 2 m = p_i \times q_i-(p_i - 1)(q_i - 1)+1+2 m=pi×qi(pi1)(qi1)+1+2
m = p i × q i − ( p i × q i − p i − q i + 1 + 1 ) + 2 m = p_i \times q_i-(p_i \times q_i - p_i - q_i+1+1)+2 m=pi×qi(pi×qipiqi+1+1)+2
m = p i × q i − p i × q i + p i + q i − 1 − 1 + 2 m = p_i \times q_i-p_i \times q_i + p_i + q_i-1-1+2 m=pi×qipi×qi+pi+qi11+2
m = p i + q i m = p_i+q_i m=pi+qi

这样我们就得到了两个式子:

n = p × q n = p \times q n=p×q
m = p + q m = p + q m=p+q

这就是韦达定理!!!
然后又发现一件事情,如果 p p p的值确定了,那么 q q q的值也就可以通过 n n n来求解,所以说可以用二分的方式,在 1 1 1~ n n n的范围里二分,从而求出答案。
但是这题还有一个更简单的方法:

O(1)做法

在刚刚的结论上再推导亿下:

e i × d i = ( p i − 1 ) ( q i − 1 ) + 1 e_i \times d_i=(p_i-1)(q_i-1)+1 ei×di=(pi1)(qi1)+1
e i × d i = p i × q i − p i − q i + 1 + 1 e_i \times d_i= p_i \times q_i-p_i-q_i+1+1 ei×di=pi×qipiqi+1+1

n = p i × q i n=p_i \times q_i n=pi×qi带入原式得:

e i × d i = n − p i − q i + 2 e_i\times d_i=n-p_i-q_i+2 ei×di=npiqi+2

把原式颠倒一下:

p i + q i = n − e i × d i + 2 p_i + q_i = n-e_i\times d_i+ 2 pi+qi=nei×di+2

所以我们就得到了以下结论:

p i + q i = n − e i × d i + 2 p_i + q_i = n-e_i\times d_i+ 2 pi+qi=nei×di+2
p i × q i = n p_i\times q_i = n pi×qi=n

那么发现一个问题: n , e , d n,e,d n,e,d都是已知的。
那就说明, p i + q i p_i + q_i pi+qi p i × q i p_i\times q_i pi×qi都是已知的。
那如何求 p i , q i p_i,q_i piqi呢?

假设两数之和是 s 1 s1 s1,两数之积是 s 2 s2 s2
a + b = s 1 a+b=s1 a+b=s1
a × b = s 2 a\times b=s2 a×b=s2
a = s 1 − b a=s1-b a=s1b
( s 1 − b ) × b = s 2 (s1-b)\times b=s2 (s1b)×b=s2
s 1 × b − b × b = s 2 s1\times b-b\times b=s2 s1×bb×b=s2

这样,就成功地用O(n)的复杂度切掉了一道橙题,滑稽~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值