我们显然知道一个一元二次方程可以表示为一般等式;其对应有解
特别地,若
,则方程无实根(也就是题中要求输出的
No Solution
)。但是从题目样例就可以看出本题的输入并不一定是一般式;可能还会出现形如
的式子;因此,我们需要对这个等式进行预先的处理,将输入内容转化为一般式后再做运算;这是本题的难点。先将等式以等号为分界划分为左右两个部分。因为左右两边的合并同类项过程一致,不妨先考虑左式。对于一个给定的代数式Algebraic Expression,其可能包括变量、符号和系数三个部分;因此可以围绕这三个部分做判定。
如果在遍历代数式字符串时遍历到了字符x
,那么就需要考虑是一次项还是二次项——若其下一位字符是^
,那么显然是二次项,否则为一次项。特别地,如果这个x
已经落在左式的最后一位,那么一定是一次项。如果遍历到的是字符+
或者-
,那么就相应地对现有一般式中对应次数项系数加上或减去下一次读入的系数。
现在考虑系数的读取。由于系数转化自对字符串的遍历过程中,所以每读取到一个数字字符就要刷新一次存储系数的变量。不妨将系数变量初始化为0;每连续读取到一次数字就将变量现有值乘以10(十进制左移一位),随后加上新读取的数字作为个位。在读取到非数字字符时,系数变量就可以推出并重新置零进行初始化了。系数后方的内容x
一定是优先于符号的,因此在处理完含变量项后如果系数变量还没有推出,那么一定是常数项;可以利用此大幅降低算法难度。特别地,非常数项的系数为1时项的系数会被省略,需要特殊处理——可以通过遍历到x
时若系数变量仍为0则置1来快速解决。
因为算理上右式左置需要变号,所以对右式的处理只需要对各系数进行与左式相反的操作即可。数学知识显然有,进而一定有
,因此求解后按此顺序输出一定可以满足“由小到大”的排列顺序。
为解释原理,代码没有采用自定义方法。
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String formula = in.nextLine();
String leftAlgebraicExpression, rightAlgebraicExpression;
// 找等号
int equalSignPosition = formula.indexOf('=');
// 以等号为界划分左右式
leftAlgebraicExpression = formula.substring(0, equalSignPosition);
rightAlgebraicExpression = formula.substring(equalSignPosition + 1,
formula.length());
int a = 0, b = 0, c = 0, coefficientTmpStorage = 0, signFlag = 1;
// 左式合并同类项
for (int i = 0; i < leftAlgebraicExpression.length(); i++) {
if (leftAlgebraicExpression.charAt(i) >= '0' &&
leftAlgebraicExpression.charAt(i) <= '9') {
// 系数暂存器
coefficientTmpStorage *= 10; // 既有系数左移一位
coefficientTmpStorage += leftAlgebraicExpression.charAt(i) - '0'; // 接待新个位
} else if (leftAlgebraicExpression.charAt(i) == 'x') {
// 一/二次项系数确定
if (coefficientTmpStorage == 0) {
// 1x可以简写为x
coefficientTmpStorage = 1;
}
if (i + 1 != leftAlgebraicExpression.length()
&& leftAlgebraicExpression.charAt(i + 1) == '^') {
// 从系数暂存器中推出存储内容作为二次项系数
a += signFlag * coefficientTmpStorage;
i += 2; // 跳过"^2"中的数字2
} else {
// 从系数暂存器中推出存储内容作为一次项系数
b += signFlag * coefficientTmpStorage;
}
coefficientTmpStorage = 0; // 暂存器初始化,准备接待新值
} else if (leftAlgebraicExpression.charAt(i) == '+') {
// 正项
c += signFlag * coefficientTmpStorage; // 此时如果暂存器还没有被初始化为0,那么存储的一定是常数项
signFlag = 1; // 符号置正
coefficientTmpStorage = 0; // 暂存器初始化
} else if (leftAlgebraicExpression.charAt(i) == '-') {
// 负项
c += signFlag * coefficientTmpStorage;
signFlag = -1; // 符号置负
coefficientTmpStorage = 0;
}
}
c += signFlag * coefficientTmpStorage; // 特殊情况:左式末项为常数项,在上述判定中没有处理
coefficientTmpStorage = 0; // 暂存器置零(初始化)
for (int i = 0; i < rightAlgebraicExpression.length(); i++) {
// 右式左置后合并同类项,原理与左式相同,但符号相反
if (rightAlgebraicExpression.charAt(i) >= '0' &&
rightAlgebraicExpression.charAt(i) <= '9') {
coefficientTmpStorage *= 10;
coefficientTmpStorage += rightAlgebraicExpression.charAt(i) - '0';
} else if (rightAlgebraicExpression.charAt(i) == 'x') {
if (coefficientTmpStorage == 0) {
coefficientTmpStorage = 1;
}
if (i + 1 != rightAlgebraicExpression.length()) {
if (rightAlgebraicExpression.charAt(i + 1) == '^') {
a -= signFlag * coefficientTmpStorage;
i += 2;
} else {
b -= signFlag * coefficientTmpStorage;
}
} else {
b -= signFlag * coefficientTmpStorage;
}
coefficientTmpStorage = 0;
} else if (rightAlgebraicExpression.charAt(i) == '+') {
c -= signFlag * coefficientTmpStorage;
signFlag = 1;
coefficientTmpStorage = 0;
} else if (rightAlgebraicExpression.charAt(i) == '-') {
c -= signFlag * coefficientTmpStorage;
signFlag = -1;
coefficientTmpStorage = 0;
}
}
c -= signFlag * coefficientTmpStorage;
// 求解 - 确定有无实根
float delta = b*b-4*a*c;
if(delta<0){
System.out.println("No Solution");
}else{
// 求解 - 求实根
double solution1 = (-b-Math.sqrt(delta))/(2*a);
double solution2 = (-b+Math.sqrt(delta))/(2*a);
System.out.println(String.format("%.2f %.2f\n", solution1, solution2));
}
}
}
#include <bits/stdc++.h>
#define _CRT_SECURE_NO_DEPRECATE
int main() {
std::string formula;
std::cin >> formula;
std::string leftAlgebraicExpression, rightAlgebraicExpression;
// 找等号,以等号界分左右两式
int equalSignPosition = formula.find("=");
leftAlgebraicExpression = formula.substr(0, equalSignPosition);
rightAlgebraicExpression = formula.substr(equalSignPosition + 1);
int a = 0, b = 0, c = 0, coefficientTmpStorage = 0, signFlag = 1;
for (int i = 0; i < leftAlgebraicExpression.size(); i++) {
// 左式合并同类项
if (leftAlgebraicExpression[i] >= '0' &&
leftAlgebraicExpression[i] <= '9') {
// 系数暂存器
coefficientTmpStorage *= 10; // 既有系数左移一位
coefficientTmpStorage += leftAlgebraicExpression[i] - '0'; // 接待新个位
} else if (leftAlgebraicExpression[i] == 'x') {
// 一/二次项系数确定
if (coefficientTmpStorage == 0) {
// 1x可以简写为x
coefficientTmpStorage = 1;
}
if (i + 1 != leftAlgebraicExpression.length()) {
if (leftAlgebraicExpression[i + 1] == '^') {
// 从系数暂存器中推出存储内容作为二次项系数
a += signFlag * coefficientTmpStorage;
i += 2; // 跳过"^2"中的数字2
} else {
// 从系数暂存器中推出存储内容作为一次项系数
b += signFlag * coefficientTmpStorage;
}
} else {
// 从系数暂存器中推出存储内容作为一次项系数
b += signFlag * coefficientTmpStorage;
}
coefficientTmpStorage = 0; // 暂存器初始化,准备接待新值
} else if (leftAlgebraicExpression[i] == '+') {
// 准备接待正项
c += signFlag * coefficientTmpStorage; // 此时如果暂存器还没有被初始化为0,那么存储的一定是常数项
signFlag = 1; // 符号置正
coefficientTmpStorage = 0; // 暂存器初始化
} else if (leftAlgebraicExpression[i] == '-') {
c += signFlag * coefficientTmpStorage;
signFlag = -1; // 符号置负
coefficientTmpStorage = 0;
}
}
c += signFlag * coefficientTmpStorage; // 特殊情况:左式末项为常数项,在上述判定中没有处理
coefficientTmpStorage = 0; // 暂存器置零(初始化),准备处理右式
for (int i = 0; i < rightAlgebraicExpression.size(); i++) {
// 右式左置后合并同类项,原理与左式相同,但符号相反
if (rightAlgebraicExpression[i] >= '0' &&
rightAlgebraicExpression[i] <= '9') {
coefficientTmpStorage *= 10;
coefficientTmpStorage += rightAlgebraicExpression[i] - '0';
} else if (rightAlgebraicExpression[i] == 'x') {
if (coefficientTmpStorage == 0) {
coefficientTmpStorage = 1;
}
if (i + 1 != rightAlgebraicExpression.length()) {
if (rightAlgebraicExpression[i + 1] == '^') {
a -= signFlag * coefficientTmpStorage;
i += 2;
} else {
b -= signFlag * coefficientTmpStorage;
}
} else {
b -= signFlag * coefficientTmpStorage;
}
coefficientTmpStorage = 0;
} else if (rightAlgebraicExpression[i] == '+') {
c -= signFlag * coefficientTmpStorage;
signFlag = 1;
coefficientTmpStorage = 0;
} else if (rightAlgebraicExpression[i] == '-') {
c -= signFlag * coefficientTmpStorage;
signFlag = -1;
coefficientTmpStorage = 0;
}
}
c -= signFlag * coefficientTmpStorage;
// 求解 - 确定有无实根
float delta = b * b - 4 * a * c;
if(delta < 0){
std::cout << "No Solution" << std::endl;
return 0;
}
// 求解 - 求实根
float solution1 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a);
float solution2 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
std::cout << std::fixed << std::setprecision(2) << solution1 << " " <<
std::fixed << std::setprecision(2) << solution2 << std::endl;
return 0;
}