2022年 CSP_J 第二轮 第二题
#CSPJ202202. [CSP-J 2022] 解密
题目描述
给定一个正整数 ,有
次询问,每次给定三个正整数
,求两个正整数
,使
、
。
输入格式
第一行一个正整数 ,表示有
次询问。
接下来 行,第
行三个正整数
。
输出格式
输出 行,每行两个正整数
表示答案。
为使输出统一,你应当保证 。
如果无解,请输出
。
样例 #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
。
【数据范围】
以下记 。
保证对于 100% 的数据,,对于任意的
,
,
,
。
测试点编号 | k≤ | n≤ | m≤ | 特殊性质 |
---|---|---|---|---|
1 | 保证有解 | |||
2 | 无 | |||
3 | 保证有解 | |||
4 | 无 | |||
5 | 保证有解 | |||
6 | 无 | |||
7 | 保证若有解则 | |||
8 | 保证有解 | |||
9 | 无 | |||
10 |
【题意】
给三个正整数,,求两个正整数
,使
,
【题解】
即解二元一次方程:
把展开一下:
已知,是个常数,那么对于
,这个等式右边都是已知的数,那么我们令
。
也就是到现在,我们有:,
,可得一元二次方程:
然后我们用一元二次方程的求根公式即可求得和
:
另外需要注意的是:输入数据中保证了 ,那么根号底下的数会超过
但不会超过
,我们需要自己编写一个二分开根号的函数。
并不是所有数据都保证有解,如果要拿满分的话,别忘了判断解的合法性(可以在求得和
的时候,来再去校验一下,来简单判断)。
【代码】
#include <bits/stdc++.h>
using namespace std;
long long solve(long long x)
{
long long left=0,right=x;
while(left<right){
long long mid=(left+right+1)/2;
if((double)mid*mid<=x){
left=mid;
}else{
right=mid-1;
}
}
return left;
}
int main()
{
//freopen("decode.in","r",stdin);
//freopen("decode.out","w",stdout);
long long t;
cin>>t;
while(t--){
long long n,e,d;
cin>>n>>e>>d;
long long m=n-e*d+2;
long long f=solve(m*m-4*n);
long long p=0,q=0;
if (f*f==(m*m-4*n)){
p=(m-f)/2;
q=(m+f)/2;
}
if((p+q)!=m || p*q!=n){
cout<<"NO"<<endl;
}else{
cout<<p<<' '<<q<<endl;
}
}
}