给定一个正整数 kk,有 kk 次询问,每次给定三个正整数 ni, ei, di,求两个正整数 pi, qi使 ni = pi *qi,di = (pi - 1)*(qi - 1) + 1。
第一行一个正整数 k,表示有 k 次询问。
接下来 k 行,第 ii 行三个正整数 ni, di, ei。
输出 k 行,每行两个正整数 pi, qi 表示答案。
为使输出统一,你应当保证 pi ≤qi。
如果无解,请输出 NO
。
输入 #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 \times d + 2m=n−e×d+2。
保证对于 100\%100% 的数据,1 \leq k \leq {10}^51≤k≤105,对于任意的 1 \leq i \leq k1≤i≤k,1 \leq n_i \leq {10}^{18}1≤ni≤1018,1 \leq e_i \times d_i \leq {10}^{18}1≤ei×di≤1018 ,1 \leq m \leq {10}^91≤m≤109。
测试点编号 | k \leqk≤ | n \leqn≤ | m \leqm≤ | 特殊性质 |
---|---|---|---|---|
11 | 10^3103 | 10^3103 | 10^3103 | 保证有解 |
22 | 10^3103 | 10^3103 | 10^3103 | 无 |
33 | 10^3103 | 10^9109 | 6\times 10^46×104 | 保证有解 |
44 | 10^3103 | 10^9109 | 6\times 10^46×104 | 无 |
55 | 10^3103 | 10^9109 | 10^9109 | 保证有解 |
66 | 10^3103 | 10^9109 | 10^9109 | 无 |
77 | 10^5105 | 10^{18}1018 | 10^9109 | 保证若有解则 p=qp=q |
88 | 10^5105 | 10^{18}1018 | 10^9109 | 保证有解 |
99 | 10^5105 | 10^{18}1018 | 10^9109 | 无 |
1010 | 10^5105 | 10^{18}1018 | 10^9109 | 无 |
分析:本题常规解法使用双重循环完成,但我们今天要探讨的是如何用一层循环解决这道题,这道题目似乎看起来只能用双重或更多层,也就是依次枚举qi,pi,找出满足条件的数,这种穷举的算法不仅很慢还很麻烦,所以.篇文章要讲的是如何用数学方法快速解决这道题。
首先分析题目给出的两个表达式:
化简可得:n-d*e+2=p+q;
设n-e*d+2=m.
为了使题目的表达式可以代入进另一个式子,从而得到运用,我们可以化简( p-q)的平方:
后为:m*m-4*
根据题目所知:若m*m-4*n<0,则无解,输出NO;
否则我们可以通过图片上的方程解出p=(m-sqrt(m*m-4*n))/2 这个时候,我们只需要判断p是否为整数,可以先定义一个double类型,再判断int(p)是否==p即可,如果等于就可以输出p和q(n/p)了,如果不等于,还是输出NO.
下面是代码:
#include
using namespace std;
typedef long long ll;
ll m,n,e,d,i,r,q;
double p;
int main(){
ios::sync_with_stdio(false);
cin>>r;
for(i=1;i<=r;i++){
cin>>n>>e>>d;
m=n-e*d+2;
if(m*m-4*n<0) cout<<"NO"<
本题是通过用数学方法来解决这道题的,从而降低了时间复杂度,只用了一层循环就做出来了。
写在最后:今天因为时间仓促,写得不够精细,之后还会优化此篇文章。