CSP-J第二轮《解密》

题目描述

给定一个正整数 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"<

本题是通过用数学方法来解决这道题的,从而降低了时间复杂度,只用了一层循环就做出来了。

写在最后:今天因为时间仓促,写得不够精细,之后还会优化此篇文章。

你可能感兴趣的:(c++)