初等数学(初中代数与几何)
初等数学(初中代数与几何)
代数(初中部分);几何(初中部分)。
概念
初等数学叶子覆盖初中代数与几何在信息学题里的直接用法,不展开竞赛级技巧。代数侧包括:一元二次方程判别式 Δ=b2−4ac、求根公式、有理数约分输出;开平方的近似(如牛顿迭代 x←2x+n/x)也属于初中延伸。几何侧在 CSP-J 初赛里常以内嵌在程序阅读中——判断平方根是否算「整」、比较近似值与 2 等。与 cspj.math.number-theory 不同:后者考整除、质数、GCD;与 cspj.cpp.mathlib 不同:后者是 sqrt、floor 等库函数怎么用,本叶子是数学结论本身(有没有实根、根式怎么化简)。
CSP-J 常考
cspj-r1-2022第 30 题:阅读牛顿法求 n 的程序,判断「k 增大时第二个输出是否必为 1」(与 n 是否为完全平方数有关)。cspj-r1-2022第 32 题:输入2 1时,迭代一次后第一个输出最接近 1.5(2 的近似)。cspj-r1-2022第 33、34 题:同一程序在不同 n,k 下输出与平方根、完全平方的代数关系。cspj-r2-2023第 3 题(一元二次方程):由 Δ 判有无实根;若有,按题面格式输出较大实根(含有理数、sqrt(r)等形式)。
#include <cmath>
// 判别式 Δ = b² - 4ac;Δ<0 无实根,Δ≥0 用求根公式(注意 a≠0)
bool hasRealRoot(long long a, long long b, long long c) {
return b * b - 4 * a * c >= 0;
}
double largerRoot(double a, double b, double c) {
double d = sqrt(b * b - 4 * a * c);
return (-b + d) / (2 * a); // 较大根
}
易错点
- 浮点比较「是否完全平方」不要用
ans * ans == n,阅读题里常考double与整数相等判定的陷阱。 - 一元二次方程输出格式题面规定很细:有理数要约分,无理数要写成
p/q+sqrt(r)等形式,漏读规则会整题零分。 - Δ=0 时两根相等,仍算「有实根」,不要输出
NO。 - 牛顿法迭代次数 k 很小时近似未必收敛,不能默认「k 越大越精确到整数 1」。
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
1 #include <iostream>22 33 using namespace std;44 55 int n,k;66 77 int solve1()88 {99 int l = 0, r = n;1010 while(l <= r){1111 int mid = (l + r) / 2;1212 if (mid * mid <= n) l = mid + 1;1313 else r = mid - 1;1414 }1515 return l - 1;1616 }1717 1818 double solve2(double x)1919 {2020 if (x == 0) return x;2121 for (int i = 0; i < k; i++)2222 x = (x + n / x) / 2;2323 return x;2424 }2525 2626 int main()2727 {2828 cin >> n >> k;2929 double ans = solve2(solve1());3030 cout << ans << ' ' << (ans * ans == n) << endl;3131 return 0;3232 }- 30判断1.5 分
对于任意输入的 n,随着所输入 k 的增大,输出的第二个数会变成 1。
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
1 #include <iostream>22 33 using namespace std;44 55 int n,k;66 77 int solve1()88 {99 int l = 0, r = n;1010 while(l <= r){1111 int mid = (l + r) / 2;1212 if (mid * mid <= n) l = mid + 1;1313 else r = mid - 1;1414 }1515 return l - 1;1616 }1717 1818 double solve2(double x)1919 {2020 if (x == 0) return x;2121 for (int i = 0; i < k; i++)2222 x = (x + n / x) / 2;2323 return x;2424 }2525 2626 int main()2727 {2828 cin >> n >> k;2929 double ans = solve2(solve1());3030 cout << ans << ' ' << (ans * ans == n) << endl;3131 return 0;3232 }- 32单选3 分
单选题
- 当输入为
2 1时,输出的第一个数最接近( )。
- 当输入为
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
1 #include <iostream>22 33 using namespace std;44 55 int n,k;66 77 int solve1()88 {99 int l = 0, r = n;1010 while(l <= r){1111 int mid = (l + r) / 2;1212 if (mid * mid <= n) l = mid + 1;1313 else r = mid - 1;1414 }1515 return l - 1;1616 }1717 1818 double solve2(double x)1919 {2020 if (x == 0) return x;2121 for (int i = 0; i < k; i++)2222 x = (x + n / x) / 2;2323 return x;2424 }2525 2626 int main()2727 {2828 cin >> n >> k;2929 double ans = solve2(solve1());3030 cout << ans << ' ' << (ans * ans == n) << endl;3131 return 0;3232 }- 33单选3 分
当输入为
3 10时,输出的第一个数最接近( )。
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
1 #include <iostream>22 33 using namespace std;44 55 int n,k;66 77 int solve1()88 {99 int l = 0, r = n;1010 while(l <= r){1111 int mid = (l + r) / 2;1212 if (mid * mid <= n) l = mid + 1;1313 else r = mid - 1;1414 }1515 return l - 1;1616 }1717 1818 double solve2(double x)1919 {2020 if (x == 0) return x;2121 for (int i = 0; i < k; i++)2222 x = (x + n / x) / 2;2323 return x;2424 }2525 2626 int main()2727 {2828 cin >> n >> k;2929 double ans = solve2(solve1());3030 cout << ans << ' ' << (ans * ans == n) << endl;3131 return 0;3232 }- 34单选3 分
当输入为
256 11时,输出的第一个数( )。
一元二次方程
C++时间 1 s内存 512 MB 文件 IO:uqe.in → uqe.out
众所周知,对一元二次方程 ax2+bx+c=0(a=0),可以用以下方式求实数解:
- 计算 Δ=b2−4ac,则:
- 若 Δ<0,则该一元二次方程无实数解。
2. 否则 Δ≥0,此时该一元二次方程有两个实数解 x1,2=2a−b±Δ。
- 若 Δ<0,则该一元二次方程无实数解。
例如:
- x2+x+1=0 无实数解,因为 Δ=12−4×1×1=−3<0。
- x2−2x+1=0 有两相等实数解 x1,2=1。
- x2−3x+2=0 有两互异实数解 x1=1,x2=2。
在题面描述中 a 和 b 的最大公因数使用 gcd(a,b) 表示。例如 12 和 18 的最大公因数是 6,即 gcd(12,18)=6。
现在给定一个一元二次方程的系数 a,b,c,其中 a,b,c 均为整数且 a=0。你需要判断一元二次方程 ax2+bx+c=0 是否有实数解,并按要求的格式输出。
在本题中输出有理数 v 时须遵循以下规则:
由有理数的定义,存在唯一的两个整数 p 和 q,满足 q>0,gcd(p,q)=1 且 v=qp。
若 q=1,则输出
{p},否则输出{p}/{q},其中{n}代表整数 n 的值;例如:
- 当 v=−0.5 时,p 和 q 的值分别为 −1 和 2,则应输出
-1/2; - 当 v=0 时,p 和 q 的值分别为 0 和 1,则应输出
0。
- 当 v=−0.5 时,p 和 q 的值分别为 −1 和 2,则应输出
对于方程的求解,分两种情况讨论:
若 Δ=b2−4ac<0,则表明方程无实数解,此时你应当输出
NO;否则 Δ≥0,此时方程有两解(可能相等),记其中较大者为 x,则:
若 x 为有理数,则按有理数的格式输出 x。
否则根据上文公式,x 可以被唯一表示为 x=q1+q2r 的形式,其中:
- $q _ 1, q _ 2$ 为有理数,且 $q _ 2 > 0$;- r 为正整数且 r>1,且不存在正整数 d>1 使 d2∣r(即 r 不应是 d2 的倍数);
此时:
- 若 q1=0,则按有理数的格式输出 q1,并再输出一个加号
+; - 否则跳过这一步输出;
随后:
- 若 q2=1,则输出
sqrt({r}); - 否则若 q2 为整数,则输出
{q2}*sqrt({r}); - 否则若 q3=q21 为整数,则输出
sqrt({r})/{q3}; - 否则可以证明存在唯一整数 c,d 满足 c,d>1,gcd(c,d)=1 且 q2=dc,此时输出
{c}*sqrt({r})/{d};
上述表示中
{n}代表整数{n}的值,详见样例。如果方程有实数解,则按要求的格式输出两个实数解中的较大者。否则若方程没有实数解,则输出
NO。
输入格式
从文件 uqe.in 中读入数据。
输入的第一行包含两个正整数 T,M,分别表示方程数和系数的绝对值上限。
接下来 T 行,每行包含三个整数 a,b,c。
输出格式
输出到文件 uqe.out 中。
输出 T 行,每行包含一个字符串,表示对应询问的答案,格式如题面所述。
每行输出的字符串中间不应包含任何空格。
样例
9 1000 1 -1 0 -1 -1 -1 1 -2 1 1 5 4 4 4 1 1 0 -432 1 -3 1 2 -4 1 1 7 1
1 NO 1 -1 -1/2 12*sqrt(3) 3/2+sqrt(5)/2 1+sqrt(2)/2 -7/2+3*sqrt(5)/2
数据范围
对于所有测试数据有:1≤T≤5000,1≤M≤103,∣a∣,∣b∣,∣c∣≤M,a=0。
| 测试点编号 | M≤ | 特殊性质 A | 特殊性质 B | 特殊性质 C |
|---|---|---|---|---|
| 1 | 1 | 是 | 是 | 是 |
| 2 | 20 | 否 | 否 | 否 |
| 3 | 103 | 是 | 否 | 是 |
| 4 | 103 | 是 | 否 | 否 |
| 5 | 103 | 否 | 是 | 是 |
| 6 | 103 | 否 | 是 | 否 |
| 7,8 | 103 | 否 | 否 | 是 |
| 9,10 | 103 | 否 | 否 | 否 |
其中:
- 特殊性质 A:保证 b=0;
- 特殊性质 B:保证 c=0;
- 特殊性质 C:如果方程有解,那么方程的两个解都是整数。
部分分
- 10 分
测试点 1:M≤1,特殊性质 A、B、C。
- 10 分
测试点 2:M≤20,无特殊性质。
- 10 分
测试点 3:M≤103,特殊性质 A、C。
- 10 分
测试点 4:M≤103,特殊性质 A。
- 10 分
测试点 5:M≤103,特殊性质 B、C。
- 10 分
测试点 6:M≤103,特殊性质 B。
- 20 分
测试点 7,8:M≤103,特殊性质 C。
- 20 分
测试点 9,10:M≤103,无特殊性质。
你的代码(C++)
提交后由评测机编译运行,结果见下方76 B / 64 KB