运用韦达定理巧解此题(完整代码见最后)
2026-07-12 20:41:46
发布于:上海
5阅读
0回复
0点赞
我们来分析一下这一题:
题目要求先输入一个整数k,表示进行次数,随后输入k行,每行三个数n,e,d。要求输出两个整数p,q,使得pq 等于n,且 ed 等于(p-1)*(q-1)+1,每输入一次换一次行。
相信许多同志开始想到的都是暴力枚举,我是先化简了第二个式子:ed = pq - p - q + 1 + 1= pq - p - q + 2,
不难发现 p + q = n - ed + 2.由此我开始从1至(p+q)/2进行遍历,如果 i(循环变量) 与 sum(就是p+q) - i 相乘等于n就直接输出。
这个方法通过了50%的样例 (不知为何我暴力枚举通过的比别人暴力通过的少) ,但这远远不够,随后我发现题目给出的条件特别满足韦达定理(对于任意一个有实根的一元二次方程,其满足 x1 + x2 = -a/b, x1*x2 = a/c)代入此题:-a/b = p + q = n - ed + 2 ,a/c = n.带回一元二次方程得:x^2 - (n - ed + 2)x + n = 0.根据根的判别式得:Δ = b^2 - 4ac = (n - ed + 2)^2 - 4n 再根据求根公式得x1 = (n - ed + 2 + sqrt(Δ))/2, x2 = (n - e*d + 2 - sqrt(Δ))/2.这里的x1,x2正是p和q。现在我们已经用已知的n,e,d代替了p和q,只需判断计算出的p和q是否为整数即可。
以下是我的代码(欢迎指正)
#include <bits/stdc++.h>
using namespace std;
signed main() {
int k;
cin >> k;
for (int i = 0;i < k;i ++){
long long n,e,d;
cin >> n >> e >> d;
double x1 = 1.0*(n - e*d + 2 - sqrt((n-e*d+2)*(n-e*d+2) - 4*n))/2;//<-求根公式带入
double x2 = 1.0*(n - e*d + 2 + sqrt((n-e*d+2)*(n-e*d+2) - 4*n))/2;//<-求根公式带入
long long x_1 = (long long)x1;//<-通过强转长整型后是否与原来相等进行判断(下同)
long long x_2 = (long long)x2;
if (x1 == x_1 && x2 == x_2) cout << x_1 << " " << x_2 << '\n';
else cout << "NO" << '\n';
}
}
给个赞不过分吧!
全部评论 1
欢迎大家提出优化空间
昨天 来自 上海
1


有帮助,赞一个