CSP-J 2023 T3 一元二次方程 解題報告
Link
前言
今年\(CSP\)的原題, 回家\(1h\)內寫\(AC\), 但是考場上沒有寫出來 , 原因是腦子太不好了, 竟然調了兩個小時沒有調出來. 一等獎懸那......
正題
看完題目,第一眼就是大模擬, 並且\(CCF\)絕對不會讓你好受,所以出了一個如此***鑽的題目, 並且要考慮到非常多的情況, 程式碼非常長......
最重要的一點: \(\Delta\)
\(\Delta\)是此題中最重要的分情況討論的地方. 根據初三\(22\)章的所學知識 ,可知分三種情況:
1. \(\Delta < 0\)
不用說了
直接輸出NO
2. \(\Delta = 0\)
同樣的, 只有一種情況, 答案為\(- \dfrac{b}{2a}\),但是, 需要嚴謹的判斷.
if(delta == 0) {
if(b == 0) {
cout << 0;
}
else if(a * b > 0) {
a = abs(a);
b = abs(b);
cout << "-";
if(b % (2 * a) == 0) {
cout << b / 2 / a;
}
else {
cout << b / __gcd(2 * a, b) << "/" << (2 * a) / __gcd(2 * a, b);
}
}
else {
a = abs(a);
b = abs(b);
if(b % (2 * a) == 0) {
cout << b / 2 / a;
}
else {
cout << b / __gcd(2 * a, b) << "/" << (2 * a) / __gcd(2 * a, b);
}
}
}
3. \(\Delta > 0\)
地獄.
我是分兩種情況的, 一種是\(a > 0\), 一種是\(a < 0\). 這樣可以分辨出是\(+ \sqrt{\Delta }\) 還是\(-\sqrt{\Delta }\)
如若\(a < 0\), 則可知答案為:
如若\(a > 0\), 則可知答案為:
- 在這裡有一個技巧, 就是不論怎樣, 輸出時, \(\sqrt{\Delta}\)永遠是正的(符號為
+
)
可以分兩種情況:
1.第一種: 不需要寫sqrt
, 也就是\(\Delta\)為完全平方數時,
比較好處理, 首先需要判斷\(b + \sqrt{\Delta}\)是否為\(0\). 如果是, 則直接輸出\(0\); 否則輸出最簡分數.
其中, 一定要記住如果\((b + \sqrt{\Delta}) \% (2 * a) = 0\), 就直接輸出一個整數.還要注意判斷正負號.
2.第二種: 需要寫sqrt
, 很難.
首先, 先輸出前面的內容, 也就是\(-\dfrac{b}{2a}\), 判斷同上.
然後, 輸出+
, 代表符號.
接著, 找出三個變數, 也就是: \(\dfrac{x}{y} \sqrt{\dfrac{\Delta}{x^2}}\)中的\(x, y和\dfrac{\Delta}{x^2}\).其中,\(\sqrt{\dfrac{\Delta}{x^2}}\)為最簡平方根數.
接下來是\(4\)種情況:
\(x = y\), 只有\(\sqrt{\dfrac{\Delta}{x^2}}\);
\(x \% y = 0\), 只有\(\dfrac{x}{y}\sqrt{\dfrac{\Delta}{x^2}}\)
\(y \% x = 0\), 只有\(\dfrac{\sqrt{\dfrac{\Delta}{x^2}}}{y}\)
其他情況, 輸出\(\dfrac{x \times \sqrt{\dfrac{\Delta}{x^2}}}{y}\)
完結撒花!!
\(Code:\)
- 心臟病患者請勿觀看
#include <bits/stdc++.h>
using namespace std;
int T, M;
int a, b, c;
int pd(int x) {
for(int i = sqrt(x) + 1; i >= 1; --i) {
if(x % (i * i) == 0) {
return i;
}
}
}
int main() {
cin >> T >> M;
while(T--) {
cin >> a >> b >> c;
int delta;
delta = b * b - 4 * a * c;
if(delta < 0) {
cout << "NO";
}
else if(delta == 0) {
if(b == 0) {
cout << 0;
}
else if(a * b > 0) {
a = abs(a);
b = abs(b);
cout << "-";
if(b % (2 * a) == 0) {
cout << b / 2 / a;
}
else {
cout << b / __gcd(2 * a, b) << "/" << (2 * a) / __gcd(2 * a, b);
}
}
else {
a = abs(a);
b = abs(b);
if(b % (2 * a) == 0) {
cout << b / 2 / a;
}
else {
cout << b / __gcd(2 * a, b) << "/" << (2 * a) / __gcd(2 * a, b);
}
}
}
else {
if(a < 0) {
int mother = - 2 * a;
int x = pd(delta);
int y = delta / x / x;
if(b == 0) {
mother = abs(mother);
if(y == 1) {
if(x == mother) {
cout << "1";
}
else if(x % mother == 0) {
cout << x / mother;
}
else {
cout << x / __gcd(x, mother) << "/" << mother / __gcd(x, mother);
}
}
else {
if(x == mother) {
cout << "sqrt(" << y << ")";
}
else if(mother % x == 0) {
cout << "sqrt(" << y << ")";
cout << "/" << mother / x;
}
else if(x % mother == 0) {
cout << x / mother << "*sqrt(" << y << ")";
}
else {
cout << x / __gcd(x, mother) << "*sqrt(" << y << ")" << "/" << mother / __gcd(x, mother);
}
}
}
else if(y == 1) { // 不需要sqrt
// 說明可以合併為同一個式子
int son = - b - x;
if(son == 0) {
cout << 0;
}
else if(son * mother < 0) { // 如果分子分母同號.
son = abs(son);
mother = abs(mother);
if(son % mother == 0) {
cout << son / mother;
}
else {
cout << son / __gcd(son, mother) << "/" << mother / __gcd(son, mother);
}
}
else { // 如果分子分母異號.
son = abs(son);
mother = abs(mother);
cout << "-";
if(son % mother == 0) {
cout << son / mother;
}
else {
cout << son / __gcd(son, mother) << "/" << mother / __gcd(son, mother);
}
}
}
else { // 需要sqrt.
// 1. 先輸出前面的
if(b > 0) { // 不需要負號
b = abs(b);
mother = abs(mother);
if(b % mother == 0) {
cout << b / mother;
}
else {
cout << b / __gcd(b, mother) << "/" << mother / __gcd(b, mother);
}
}
else { // 需要負號
b = abs(b);
mother = abs(mother);
cout << "-";
if(b % mother == 0) {
cout << b / mother;
}
else {
cout << b / __gcd(b, mother) << "/" << mother / __gcd(b, mother);
}
}
// 2. 輸出sqrt部分(不管怎樣都是+)
cout << "+";
if(x == 1) { // 不需要輸出字首.
cout << "sqrt(" << y << ")";
cout << "/" << - 2 * a;
}
else {
if(x == mother) {
cout << "sqrt(" << y << ")";
}
else if(x % mother == 0) {
cout << x / mother << "*sqrt(" << y << ")";
}
else if(mother % x == 0) {
cout << "sqrt(" << y << ")";
cout << "/" << mother / x;
}
else {
cout << x / __gcd(x, mother);
cout << "*sqrt(" << y << ")";
cout << "/" << mother / __gcd(x, mother);
}
}
}
}
else {
int mother = 2 * a;
int x = pd(delta);
int y = delta / x / x;
if(b == 0) {
mother = abs(mother);
if(y == 1) {
if(x == mother) {
cout << "1";
}
else if(x % mother == 0) {
cout << x / mother;
}
else {
cout << x / __gcd(x, mother) << "/" << mother / __gcd(x, mother);
}
}
else {
if(x == mother) {
cout << "sqrt(" << y << ")";
}
else if(mother % x == 0) {
cout << "sqrt(" << y << ")";
cout << "/" << mother / x;
}
else if(x % mother == 0) {
cout << x / mother << "*sqrt(" << y << ")";
}
else {
cout << x / __gcd(x, mother) << "*sqrt(" << y << ")" << "/" << mother / __gcd(x, mother);
}
}
}
else if(y == 1) { // 不需要sqrt
// 說明可以合併為同一個式子
int son = - b + x;
if(son == 0) {
cout << 0;
}
else if(son * mother > 0) { // 如果分子分母同號.
son = abs(son);
mother = abs(mother);
if(son % mother == 0) {
cout << son / mother;
}
else {
cout << son / __gcd(son, mother) << "/" << mother / __gcd(son, mother);
}
}
else { // 如果分子分母異號.
son = abs(son);
mother = abs(mother);
cout << "-";
if(son % mother == 0) {
cout << son / mother;
}
else {
cout << son / __gcd(son, mother) << "/" << mother / __gcd(son, mother);
}
}
}
else { // 需要sqrt.
// 1. 先輸出前面的
if(b * mother < 0) { // 不需要負號
b = abs(b);
mother = abs(mother);
if(b % mother == 0) {
cout << b / mother;
}
else {
cout << b / __gcd(b, mother) << "/" << mother / __gcd(b, mother);
}
}
else { // 需要負號
b = abs(b);
mother = abs(mother);
cout << "-";
if(b % mother == 0) {
cout << b / mother;
}
else {
cout << b / __gcd(b, mother) << "/" << mother / __gcd(b, mother);
}
}
// 2. 輸出sqrt部分(不管怎樣都是+)
cout << "+";
if(x == 1) { // 不需要輸出字首.
cout << "sqrt(" << y << ")";
cout << "/" << 2 * a;
}
else {
mother = 2 * a;
if(x == mother) {
cout << "sqrt(" << y << ")";
}
else if(x % mother == 0) {
cout << x / mother << "*sqrt(" << y << ")";
}
else if(mother % x == 0) {
cout << "sqrt(" << y << ")";
cout << "/" << mother / x;
}
else {
cout << x / __gcd(x, mother);
cout << "*sqrt(" << y << ")";
cout << "/" << mother / __gcd(x, mother);
}
}
}
}
}
cout << endl;
}
return 0;
}