题目
链接
https://www.luogu.com.cn/problem/P8814?contestId=90215
字面描述
题目描述
给定一个正整数 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=(pi−1)(qi−1)+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 pi≤qi。
如果无解,请输出 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.in
与 decode/decode2.ans
。
【样例 #3】
见附件中的 decode/decode3.in
与 decode/decode3.ans
。
【样例 #4】
见附件中的 decode/decode4.in
与 decode/decode4.ans
。
【数据范围】
以下记 m = n − e × d + 2 m = n - e \times d + 2 m=n−e×d+2。
保证对于
100
%
100\%
100% 的数据,
1
≤
k
≤
10
5
1 \leq k \leq {10}^5
1≤k≤105,对于任意的
1
≤
i
≤
k
1 \leq i \leq k
1≤i≤k,
1
≤
n
i
≤
10
18
1 \leq n_i \leq {10}^{18}
1≤ni≤1018,
1
≤
e
i
×
d
i
≤
10
18
1 \leq e_i \times d_i \leq {10}^{18}
1≤ei×di≤1018
,
1
≤
m
≤
10
9
1 \leq m \leq {10}^9
1≤m≤109。
测试点编号 | 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 | 无 |
思路分析
数据分析
题目中的,n,e,d均已给出。求p,q
大概关系如下:
n=pq;
ed=(p-1)(q-1)+1;
=pq-p-q+2
题目中给了一个m 值的定义
m=n-ed+2; 代入n,ed;
m=pq-pq+p+q-2+2
=p+q;
若把所有已经知道的罗列起来,条件如下:
n-ed+2=p+q;
n =pq;
根据这2个关系式,是可以看出p,q取值的唯一性。
那么只要知道p的值,q的值一定确定.
方法
接下来面临的问题是如何确定p的值
枚举
-
m的最大取值范围是1e9 枚举 时间复杂度 O(km) TLE
-
从n入手
像分解因数一样 枚举范围是sqrt(n) -> 时间复杂度 O(k* sqrt(n)) 大大的TLE!
以上两种方法写对的得分都是60分;
二分
接下来是不是没有想法了
别急
最重要的思路就是二分
p
,上限
1
e
9
;
最重要的思路就是 二分p,上限1e9;
最重要的思路就是二分p,上限1e9;
单次二分时间复杂度
O
(
l
o
g
(
m
)
)
60
单次二分时间复杂度 O(log(m))~60
单次二分时间复杂度O(log(m)) 60
总体时间复杂度 O(k*log(m))~6e6
时间复杂度过的去。
接下来的问题是,此解空间是否有单调有序性。
n == pq 返回pq的值
n>pq,n<pq 应该往哪个方向二分
当p大的时候,q小
q小的时候,p大
这对标了小学时的和同近积大
∴
这个解空间不具有单调有序性,但这个解空间具有单调对称性
,
所以
n
>
p
q
可以往任意方向二分搜索,
n
<
p
q
往反方向二分即可。
∴这个解空间不具有单调有序性,但这个解空间具有单调对称性,所以n>pq可以往任意方向二分搜索,n<pq往反方向二分即可。
∴这个解空间不具有单调有序性,但这个解空间具有单调对称性,所以n>pq可以往任意方向二分搜索,n<pq往反方向二分即可。
思路说的差不多了,上代码
代码实现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int k;
ll n,e,d,ans;
int main(){
freopen("decode.in","r",stdin);
freopen("decode.out","w",stdout);
scanf("%d",&k);
while(k--){
scanf("%lld%lld%lld",&n,&e,&d);
e=(ll)e*d;
ll m=n-e;
ll l=1,r=m+1;
ans=0;
while(l<=r){
ll mid=(l+r)>>1;
ll c=m-mid+2;
ll cnt=(ll)c*mid;
if(cnt>n)r=mid-1;
else if(cnt<n)l=mid+1;
else {
ans=mid;
break;
}
}
ll cc=m-ans+2;
if(ans*cc!=n)printf("NO\n");
else printf("%lld %lld\n",min(ans,cc),max(ans,cc));
}
return 0;
}