【题解】【模拟】—— [CSP-J 2023] 一元二次方程

news2024/9/23 9:36:13

【题解】【模拟】—— [CSP-J 2023] 一元二次方程

  • [CSP-J 2023] 一元二次方程
    • 题目背景
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例
      • 输入 #1
      • 输出 #1
    • 提示
  • 1.题意解析
  • 2.AC代码

[CSP-J 2023] 一元二次方程

戳我查看题目(洛谷)

题目背景

众所周知,对一元二次方程 a x 2 + b x + c = 0 , ( a ≠ 0 ) ax ^ 2 + bx + c = 0, (a \neq 0) ax2+bx+c=0,(a=0),可以用以下方式求实数解:

  • 计算 Δ = b 2 − 4 a c \Delta = b ^ 2 - 4ac Δ=b24ac,则:
    1. Δ < 0 \Delta < 0 Δ<0,则该一元二次方程无实数解。
    2. 否则 Δ ≥ 0 \Delta \geq 0 Δ0,此时该一元二次方程有两个实数解 x 1 , 2 = − b ± Δ 2 a x _ {1, 2} = \frac{-b \pm \sqrt \Delta}{2a} x1,2=2ab±Δ

例如:

  • x 2 + x + 1 = 0 x ^ 2 + x + 1 = 0 x2+x+1=0 无实数解,因为 Δ = 1 2 − 4 × 1 × 1 = − 3 < 0 \Delta = 1 ^ 2 - 4 \times 1 \times 1 = -3 < 0 Δ=124×1×1=3<0
  • x 2 − 2 x + 1 = 0 x ^ 2 - 2x + 1 = 0 x22x+1=0 有两相等实数解 x 1 , 2 = 1 x _ {1, 2} = 1 x1,2=1
  • x 2 − 3 x + 2 = 0 x ^ 2 - 3x + 2 = 0 x23x+2=0 有两互异实数解 x 1 = 1 , x 2 = 2 x _ 1 = 1, x _ 2 = 2 x1=1,x2=2

在题面描述中 a a a b b b 的最大公因数使用 gcd ⁡ ( a , b ) \gcd(a, b) gcd(a,b) 表示。例如 12 12 12 18 18 18 的最大公因数是 6 6 6,即 gcd ⁡ ( 12 , 18 ) = 6 \gcd(12, 18) = 6 gcd(12,18)=6

题目描述

现在给定一个一元二次方程的系数 a , b , c a, b, c a,b,c,其中 a , b , c a, b, c a,b,c 均为整数且 a ≠ 0 a \neq 0 a=0。你需要判断一元二次方程 a x 2 + b x + c = 0 a x ^ 2 + bx + c = 0 ax2+bx+c=0 是否有实数解,并按要求的格式输出。

在本题中输出有理数 v v v 时须遵循以下规则:

  • 由有理数的定义,存在唯一的两个整数 p p p q q q,满足 q > 0 q > 0 q>0 gcd ⁡ ( p , q ) = 1 \gcd(p, q) = 1 gcd(p,q)=1 v = p q v = \frac pq v=qp

  • q = 1 q = 1 q=1则输出 {p},否则输出 {p}/{q},其中 {n} 代表整数 n n n 的值;

  • 例如:

    • v = − 0.5 v = -0.5 v=0.5 时, p p p q q q 的值分别为 − 1 -1 1 2 2 2,则应输出 -1/2
    • v = 0 v = 0 v=0 时, p p p q q q 的值分别为 0 0 0 1 1 1,则应输出 0

对于方程的求解,分两种情况讨论:

  1. Δ = b 2 − 4 a c < 0 \Delta = b ^ 2 - 4ac < 0 Δ=b24ac<0,则表明方程无实数解,此时你应当输出 NO

  2. 否则 Δ ≥ 0 \Delta \geq 0 Δ0,此时方程有两解(可能相等),记其中较大者为 x x x,则:

    1. x x x 为有理数,则按有理数的格式输出 x x x

    2. 否则根据上文公式, x x x 可以被唯一表示为 x = q 1 + q 2 r x = q _ 1 + q _ 2 \sqrt r x=q1+q2r 的形式,其中:

      • q 1 , q 2 q _ 1, q _ 2 q1,q2 为有理数,且 q 2 > 0 q _ 2 > 0 q2>0
      • r r r 为正整数且 r > 1 r > 1 r>1,且不存在正整数 d > 1 d > 1 d>1 使 d 2 ∣ r d ^ 2 \mid r d2r(即 r r r 不应是 d 2 d ^ 2 d2 的倍数);

    此时:

    1. q 1 ≠ 0 q _ 1 \neq 0 q1=0,则按有理数的格式输出 q 1 q _ 1 q1,并再输出一个加号 +
    2. 否则跳过这一步输出;

    随后:

    1. q 2 = 1 q _ 2 = 1 q2=1,则输出 sqrt({r})
    2. 否则若 q 2 q _ 2 q2 为整数,则输出 {q2}*sqrt({r})
    3. 否则若 q 3 = 1 q 2 q _ 3 = \frac 1{q _ 2} q3=q21 为整数,则输出 sqrt({r})/{q3}
    4. 否则可以证明存在唯一整数 c , d c, d c,d 满足 c , d > 1 , gcd ⁡ ( c , d ) = 1 c, d > 1, \gcd(c, d) = 1 c,d>1,gcd(c,d)=1 q 2 = c d q _ 2 = \frac cd q2=dc,此时输出 {c}*sqrt({r})/{d}

    上述表示中 {n} 代表整数 {n} 的值,详见样例。

    如果方程有实数解,则按要求的格式输出两个实数解中的较大者。否则若方程没有实数解,则输出 NO

输入格式

输入的第一行包含两个正整数 T , M T, M T,M,分别表示方程数和系数的绝对值上限。

接下来 T T T 行,每行包含三个整数 a , b , c a, b, c a,b,c

输出格式

输出 T T T 行,每行包含一个字符串,表示对应询问的答案,格式如题面所述。

每行输出的字符串中间不应包含任何空格

输入输出样例

输入 #1

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

1
NO
1
-1
-1/2
12*sqrt(3)
3/2+sqrt(5)/2
1+sqrt(2)/2
-7/2+3*sqrt(5)/2

提示

【样例 #2】

见附件中的 uqe/uqe2.inuqe/uqe2.ans

【数据范围】

对于所有数据有: 1 ≤ T ≤ 5000 1 \leq T \leq 5000 1T5000 1 ≤ M ≤ 1 0 3 1 \leq M \leq 10 ^ 3 1M103 ∣ a ∣ , ∣ b ∣ , ∣ c ∣ ≤ M |a|,|b|,|c| \leq M a,b,cM a ≠ 0 a \neq 0 a=0

测试点编号 M ≤ M \leq M特殊性质 A特殊性质 B特殊性质 C
1 1 1 1 1 1
2 2 2 20 20 20
3 3 3 1 0 3 10 ^ 3 103
4 4 4 1 0 3 10 ^ 3 103
5 5 5 1 0 3 10 ^ 3 103
6 6 6 1 0 3 10 ^ 3 103
7 , 8 7, 8 7,8 1 0 3 10 ^ 3 103
9 , 10 9, 10 9,10 1 0 3 10 ^ 3 103

其中:

  • 特殊性质 A:保证 b = 0 b = 0 b=0
  • 特殊性质 B:保证 c = 0 c = 0 c=0
  • 特殊性质 C:如果方程有解,那么方程的两个解都是整数。

1.题意解析

    这是我第一次自己做出来的大模拟!!!

    遇到这种大模拟,思路大体就是将题目分成几个模块。

    比如分析这道题,我们可以将它分成三个模块:

1.没有解,即 Δ < 0 \Delta<0 Δ<0
2.解可以化成有理数,即 Δ \Delta Δ为完全平方数,存在一整数r,使得 r ∗ r = Δ r*r=\Delta rr=Δ
3.解不可以化成有理数,和上一条相反。

长文警告!!!


先看第一条

    这是最好解决的。读入t组数据,先算出这组数据的 Δ \Delta Δ,再判断是否 < 0 <0 <0就行了。示例如下:

while(t--)
{
    int a,b,c,delta;
	scanf("%d%d%d",&a,&b,&c);
	delta=b*b-4*a*c;//求出Δ
	if(delta<0)//情况1,Δ小于0,无解
	{
		printf("NO\n");
		continue;
	}
}

然后是第二条

    首先定义一个函数is_perfect_pow_2_num,用来判断一个数是不是完全平方数。

bool is_perfect_pow_2_num(int num)//判断是否是完全平方数的函数 
{
	return pow((int)sqrt(num),2)==num;//隐式类型转换 
}

如果看不懂,可以去看看【归纳】常见函数模版和解析中的第四条。

然后判断 Δ \Delta Δ是不是完全平方数,即

if(is_prefect_pow_2_num(delta))

    因为题目要求我们求最大值,我们只要化简 x 1 , 2 = − b ± Δ 2 a x _ {1, 2} = \frac{-b \pm \sqrt \Delta}{2a} x1,2=2ab±Δ ,然后求出两者中的较大值就可以了。

为什么不直接取 x = − b + Δ 2 a x=\frac{-b+\sqrt \Delta}{2a} x=2ab+Δ 呢?
看看这一组数据就知道了。
-1 -12 108// Δ = 576 \Delta=576 Δ=576
输出:-18。正确答案:6
这是因为,如果分母带有负数,那么整个分数也会变成负的。但只要我们让分子也变成负数,上下就抵消了。所以我们为了避免这种情况的发生,会选择两者都算一遍。

那么思路基本就是这样了。但还有两个需要注意的点:

1.分数要化简;
2.分母为 1 1 1不需要输出。

那么定义一个用来化简的函数simplify,后面需要用到。

void simplify(int &mum,int &son)//将一个分数化简的函数,记得加上&变成应用传参 
{
	int gcd=__gcd(mum,son);//求出分子分母最大公因数 
	mum/=gcd;son/=gcd;//化简 
	if(son<0)son*=-1,mum*=-1;//将-1转移到分子上 
}

那么接下来就跟着这个思路去模拟就行了。

if(is_perfect_pow_2_num(delta))//情况2,解能化成有理数
{
		//求出两种情况并进行比较
		int mum1=-1*b+sqrt(delta),mum2=-1*b-sqrt(delta);
		int son1=2*a,son2=2*a;
		int mum,son;//储存较大的分数的分母和分子
		simplify(mum1,son1);//化简分数1
		simplify(mum2,son2);//化简分数2
		if(mum1*1.0/son1>mum2*1.0/son2)//取分数值较大的分数 
			mum=mum1,son=son1;
		else
			mum=mum2,son=son2;
		printf("%d",mum);
		if(son!=1)//分子为1,就不输出分子
			printf("/%d",son);
		puts("");//换行,相当于putchar('\n')或cout<<endl;
}

最后是第三条

    对于这种情况,我们将 − b ± Δ 2 a \frac{-b \pm \sqrt \Delta}{2a} 2ab±Δ 拆解为 − b 2 a + ∣ Δ 2 a ∣ \frac{-b}{2a}+|\frac{\sqrt \Delta}{2a}| 2ab+2aΔ

这里为什么可以这样做呢?
    因为 ± Δ 2 a \pm \frac{\sqrt \Delta}{2a} ±2aΔ 化简后为 ± q 2 r ÷ q 3 2 a \pm \frac{q _ 2 \sqrt r \div q_3}{2a} ±2aq2r ÷q3,因为是乘除法,所以两者的绝对值是相等的。那么我们就不需要关心它的正负,它如果是正数我们就给它+,否则给它-。无论怎样,它最后的值一定是正的,也就一定是最大的。

    然后就是如何求 q 2 q_2 q2 q 3 q_3 q3了。根据算数平方根的运算法则,我们可以将 Δ \sqrt \Delta Δ 转换成如下形式: Δ = q 2 r = q 2 ∗ q 2 ∗ r \sqrt \Delta=q_2\sqrt r=\sqrt{q2*q2*r} Δ =q2r =q2q2r

    那么我们就将问题转换成了:求一个最大的 q 2 q_2 q2,使得 q 2 ∗ q 2 ∗ r = Δ ( r ∈ N , 即 r 是自然数 ) q2*q2*r=\Delta(r\in\mathbb{N},即r是自然数) q2q2r=Δ(rN,r是自然数)。只需要枚举 q 2 q_2 q2,求出 r r r就行了。注意:只要枚举到r2*r2<n就行了。

    要注意的是,如果枚举到最后连一个合适的 q 2 q_2 q2都没有,那么就不用进行后面的化简和输出了。

    求出 q 2 q_2 q2之后,就使用我们前面分装的simplify函数化简 q 2 q_2 q2 q 3 q_3 q3

    最后,如果有合适的 q 2 q_2 q2 q 3 q_3 q3,那么就输出。记得输出一个换行。

    完结撒花!

2.AC代码

#include<bits/stdc++.h>
using namespace std;
bool is_perfect_pow_2_num(int num)//判断是否是完全平方数的函数 
{
	return pow((int)sqrt(num),2)==num;//隐式类型转换 
}
void simplify(int &mum,int &son)//将一个分数化简的函数 
{
	int gcd=__gcd(mum,son);//求出分子分母最大公因数 
	mum/=gcd;son/=gcd;//化简 
	if(son<0)son*=-1,mum*=-1;//将-1转移到分子上 
}
int main()
{
    int t,m;
    scanf("%d%d",&t,&m);
    while(t--)
    {
    	int a,b,c,delta;
		scanf("%d%d%d",&a,&b,&c);
		delta=b*b-4*a*c;//求出Δ
		if(delta<0)//情况1,Δ小于0,无解
		{
			printf("NO\n");
			continue;
		}
		if(is_perfect_pow_2_num(delta))//情况2,解能化成有理数
		{
			//求出两种情况并进行比较
			int mum1=-1*b+sqrt(delta),mum2=-1*b-sqrt(delta);
			int son1=2*a,son2=2*a;
			int mum,son;//储存较大的分数的分母和分子
			simplify(mum1,son1);//化简分数1
			simplify(mum2,son2);//化简分数2
			if(mum1*1.0/son1>mum2*1.0/son2)//取分数值较大的分数 
			    mum=mum1,son=son1;
			else
			    mum=mum2,son=son2;
			printf("%d",mum);
			if(son!=1)//分子为1,就不输出分子
			    printf("/%d",son);
			puts("");
		}
		else//情况3,解只能化成无理数
		{
			int q1_mum=-1*b,q1_son=2*a,q2,r,q3=2*a;//变量名如题
			simplify(q1_mum,q1_son);//化简 
			for(int i=1;i*i<=delta;i++)//找出最大的q2 
			{
				if(delta%(i*i)!=0)continue;//如果能整除 
				q2=i;//更新q2 
				r=delta/(q2*q2);//求出r 
			}
			if(q2*q2<=delta)simplify(q2,q3);//如果有符合条件的q2,化简 
			q2=abs(q2);//求出绝对值 
			if(q1_mum*1.0/q1_son!=0)//输出q1 
			    if(q1_son==1)
				    printf("%d+",q1_mum);
			    else
				    printf("%d/%d+",q1_mum,q1_son);
			if(q2!=1&&q2*q2<=delta)//输出q2(如果有符合条件的q2的话)
			    printf("%d*",q2);
			printf("sqrt(%d)",r);//输出r 
			if(q3!=1)//输出q3(如果有符合条件的q3的话)
			    printf("/%d",q3);
			puts("");
		}
	}
	return 0;
}

喜欢就订阅此专辑吧!

【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。

欢迎扫码关注蓝胖子编程教育
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

共享文件操作记录如何查看?这种方法帮你轻松实现

查看共享文件操作记录&#xff0c;可以通过以下几种方法实现&#xff1a; 一、利用操作系统的文件访问记录功能 在Windows操作系统中&#xff0c;可以利用“事件查看器”来查看共享文件的访问记录。事件查看器是Windows内置的一个工具&#xff0c;用于记录系统中发生的各种事…

50个必知的ChatGPT学术论文指令:提升研究效率,强烈推荐收藏!

随着AI技术的发展&#xff0c;AI已经成为学术创作的强大工具。如果你还不了解如何利用AI润色你的论文&#xff0c;那么这篇文章将为你提供极大的帮助。我们精心整理了50个顶级ChatGPT学术论文指令&#xff0c;强烈建议你加以利用&#xff01; 这些指令非常实用&#xff0c;能显…

线性表的顺序表示—插入操作

线性表的顺序表示—插入操作 插入代码 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define InitSize 15 // 初始化扩容长度 #define MaxSize 100typedef struct {int data[MaxSize]; // 申请空间&#xff08;静态&#xff09;int lengt…

探索ISP自动曝光技术:工作原理与应用(一)

在现代数码相机和智能手机中&#xff0c;图像信号处理器&#xff08;ISP&#xff09;是负责将传感器捕捉到的原始数据转换成高质量图像的重要组件。而在ISP的众多功能中&#xff0c;自动曝光&#xff08;Auto Exposure, AE&#xff09;是确保拍摄出清晰、明亮且细节丰富照片的关…

QT Quick QML 实例之定制 TableView

QT Quick QML 实例之定制 TableView 一、演示二、C关键步骤1. beginInsertRows()&#xff08;用户插入行&#xff09;2. roleNames() &#xff08;表格中列映射&#xff09;3. data() &#xff08;用户获取数据&#xff09;4. headerData() &#xff08;表头&#xff09;5. fla…

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04后适配SONY索尼的HDMI OUT的机芯8530

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04后适配SONY索尼的HDMI OUT的机芯8530 2024/8/24 16:33 echo 8 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio8/direction echo 1 > /sys/class/gpio/gpio8/value 1、HDMI IN 4K 2024/7/25 18:01 v4l2-ctl -…

文件—python

一、文件编码 对于同一份文件&#xff0c;人的视角和计算机的视角是不相同的&#xff0c;人看到的是文字&#xff0c;计算机看到的0和1组成的编码。因为计算机只能识别0和1&#xff0c;无法直接识别文字&#xff0c;那我们是如何在电脑上看到文字的呢&#xff1f; 计算机按照一…

C++的动态数组vector番外之capacity

今日诗词&#xff1a; 爱他明月好&#xff0c;憔悴也相关。 西风多少恨&#xff0c;吹不散眉弯。 ——《临江仙寒柳》【清】纳兰容若 目录 引言 正文 string中的和vector中的capacity有什么区别 vector扩容时内存分配的策略是什么&#xff1f; capacity在vector中的表现如…

基于无人机边沿相关 ------- IBUS、SBUS协议和PPM信号

文章目录 一、IBUS协议二、SBUS协议三、PPM信号 一、IBUS协议 IBUS&#xff08;Intelligent Bus&#xff09;是一种用于电子设备之间通信的协议&#xff0c;采用串行通信方式&#xff0c;允许多设备通过单一数据线通信&#xff0c;较低延迟&#xff0c;支持多主机和从机结构&a…

redis | Django小项目之Mysql数据库和Redis缓存的应用

Django小项目 需求整体架构图技术细节环境配置各文件配置settings.pyurls.pyviews.pyuser_update.html 结果相关代码补充r.hgetall(cacahe_key)new_data {k.decode():v.decode() for k,v in data.items()} 需求 整体架构图 技术细节 环境配置 django-admin startprojrct rmysi…

WIFI 应用层代码

1.0 定义枚举类型 typedef enum {WIFI_COMM_WAIT, // AT 等待命令WIFI_COMM_OK, // AT 命令完成WIFI_COMM_FALL, // AT 命令失败 }WifiCommState_t; 注&#xff1a;该枚举类型的作用是&#xff0c;定义三个成员变量&#xff0c;分别表示AT指令等待发送&#xff0c;AT指令…

unity游戏开发——(细)深入解析 Unity 地形系统:从基础到高级应用

Unity游戏开发 “好读书&#xff0c;不求甚解&#xff1b;每有会意&#xff0c;便欣然忘食。” 本文目录&#xff1a; Unity游戏开发 Unity游戏开发前言深入解析 Unity 地形系统&#xff1a;从基础到高级应用一、初识 Unity 地形系统1. 地形尺寸与分辨率 二、地形编辑工具详解1…

下拉菜单 匹配搜索

操作版本&#xff1a;Excel 2010 下拉菜单 涉及到的函数&#xff1a; INDIRECT函数&#xff1a;返回由文本字符串指定的引用 原文链接 一级下拉菜单 方法一&#xff1a;手动输入 选中要制作下拉菜单的单元格区域&#xff0c;单击【数据】-【数据有效性】-【序列】&#…

15.CentOS7升级内核

升级内核 1.配置镜像源 vim /etc/yum.repos.d/elrepo.repo[elrepo] nameelrepo baseurlhttps://mirrors.aliyun.com/elrepo/archive/kernel/el7/x86_64 gpgcheck0 enabled12.备份 cd /etc/yum.repos.d/ mv local.repo repo.bak/ 3.清缓存 yum clean all 4.升级内核 yum ins…

背部筋膜炎最好的恢复办法

背部筋膜炎是由于寒冷、精神紧张、潮湿或慢性劳损等因素造成的背部肌筋膜和肌组织发生水肿、纤维变性和渗出&#xff0c;其主要症状包括&#xff1a; 1、疼痛&#xff1a;患者通常会出现背部疼痛&#xff0c;这种疼痛在着凉或劳累时可能会加重。晨起时疼痛可能尤为明显&#x…

将两对象(重复属性不替换)合并成一个对象

将这两个对象合并成一个对象 const obj1 {"configType": "all","config": {"a":1} };const obj2 {"target_cluster": "dev-0821","type": "import","config": {"connector…

攻防世界-web题型-4星难度汇总-个人wp

Confusion1 进入页面查看源代码&#xff0c;发现有两个提示 访问第一个源码里面有个 /opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt /opt/salt_b420e8cfb8862548e68459ae1d37a1d5.txt 不过我发现好像是只要访问404页面都有这两个。。。 另外这两个admin和login页面都没用…

如何把照片转换成PDF格式?分享3种好用的PDF转换方法

在数字化的时代中&#xff0c;各种格式的文件已经是我们平时办公中不可或缺的一部分&#xff0c;其中尤其是以图片、PDF这两种文件使用的最多&#xff0c;图片能够更加直观的表现内容&#xff0c;而PDF文档因其稳定性、兼容性等特性&#xff0c;也在办公中有独特的优势&#xf…

Pandas DataFrame的创建方法(Create DataFrame)

pandas是一个第三方数据分析库&#xff0c;其集成了大量的数据模型和分析工具&#xff0c;可以方便的处理和分析各类数据。其中主要对象类型有Series&#xff0c;DataFrame和Index。本文介绍DataFrame对象的基本创建方法。 关于DataFrame的基础用法&#xff0c;可以查看下面的…

随机生成n个字节os.urandom(n)

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 随机生成n个字节 os.urandom(n) [太阳]选择题 下列输出结果中正确的是? import os print("【执行】a os.urandom(2)") a os.urandom(2) print("【显示】a ", a) pri…