洛谷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;
}
posted @ 2025-06-26 13:52  2789617221guo  阅读(82)  评论(0)    收藏  举报