洛谷P8814 [CSP-J 2022] 解密 题解
本题做法
- 数学。
思路
记 \(n=pq\) 为式 1,\(ed=(p-1)(q-1)+1\) 为式 2。
将式 2 展开,得到 \(ed=pq-p-q+2\),移项得到 \(p+q=pq-ed+2=n-ed+2\),正好是数据范围中定义的 \(m\)。
这样,我们就得到了 2 个式子:
\[pq=n\\
p+q=n-ed+2(式 3)
\]
敏锐察觉到,我们需要求出 \(p-q\),那这怎么求呢?回忆完全平方公式:\((p±q)^2=p^2±2pq+q^2\)。将 \((p+q)^2-(p-q)^2\) 得到 \((p+q)^2-(p-q)^2=4pq\),移项得到 \((p-q)^2=(p+q)^2-4pq\),两侧同时开根号得到 \(p-q=\sqrt{(p+q)^2-4pq}\),代入上面的 2 个式子得到 \(p-q=\sqrt{(n-ed+2)^2-4n}\),这个式子我们记为式 4。
将式 3 和式 4 相加,得到 \(2p=n-ed+2+\sqrt{(n-ed+2)^2-4n}\),两遍同时除以 2 得到 \(p=\dfrac{n-ed+2+\sqrt{(n-ed+2)^2-4n}}{2}\),将式 3 变化得到 \(q-n-ed+2-p\),代入 \(p\) 得到 \(q=\dfrac{n-ed+2-\sqrt{(n-ed+2)^2-4n}}{2}\),使用给定的数据求出 \(p,q\) 后根据式 1 和式 2 验证是否输出 \(\texttt{NO}\) 即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const double EPS=1e-8;
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int k;
cin>>k;
while(k--){
long long n,d,e;
cin>>n>>d>>e;
long long p=(n-e*d+2+sqrt((n-e*d+2)*(n-e*d+2)-4*n))/2;
long long q=(n-e*d+2-sqrt((n-e*d+2)*(n-e*d+2)-4*n))/2;
if(p*q==n&&e*d==(p-1)*(q-1)+1&&p&&q) cout<<min(p,q)<<" "<<max(p,q)<<endl;
else cout<<"NO"<<endl;
}
return 0;
}

浙公网安备 33010602011771号