P9750 [CSP-J 2023] 一元二次方程
你说的对,但是我期中考前来写题解。
从头开始想这个题,比较抽象的模拟题。
首先几个注意的事项以及一些细节:
-
下文提到的化简,指的是对于分子分母同时除以他们的最大公因数。同时注意如果分母是 ,直接输出分子即可。
-
下文提到的对分母的正负性讨论,指的是如果分母可能是正数或者负数,那么讨论分子可能出现的情况。假设如果分母是负数,枚举分子可能出现的两负,两正,一正一负,发现如果要取最大值的话,要求分子尽可能的小,那就是说明 要取负号,分母是正的同理。可以发现,这个取法和 的值无关。
首先对于 ,显然无解。
如果 ,那我们只用输出 即可。这两个都是整数,直接化简。
如果 ,那么我们考虑先把 算出来,因为它最多也是到 ,所以一种方法是直接枚举他的最大的平方因子,但是这个人脑抽用了预处理质数然后看每个质数的偶数次平方还获得最大平方因子的方法。仅供参考。
为了方便,我们把 和 分开考虑。这时候再考虑,如果 恰好是一个完全平方数,那么它势必可以和前面的 合并起来,在这里对分母的正负性讨论,同时化简,否则如果不是完全平方数,那就分开化简以后再进行对分母的正负性讨论。
同时注意 的情况,因为分开来看了,这时候不能输出前置的 。
代码写得比较抽象。
#include<bits/stdc++.h>
using namespace std;
const int N =4e4+10;
int Prime[N],num;
bool vis[N];
int GCD(int a,int b){
if(b==0) return a;
return GCD(b,a%b);
}
int Quickpow(int a,int b){
int ans=a,now=1;
while(b>0){
if(b&1) now*=ans;
ans*=ans;
b>>=1;
}
return now;
}
void init(){
for(int i=2;i<=32000;i++){
if(vis[i]==false) Prime[++num]=i;
for(int j=1;j<=num&&i*Prime[j]<=32000;j++){
vis[i*Prime[j]]=true;
if(i%Prime[j]==0)
break;
}
}
}
int main(){
// freopen("uqe.in","r",stdin);
// freopen("uqe.out","w",stdout);
init();
int t,M;
cin>>t>>M;
while(t--){
int a,b,c;
cin>>a>>b>>c;
int now=b*b-4*a*c;
if(b*b-4*a*c<0) {cout<<"NO"<<endl;continue;}
if(b*b-4*a*c==0&&b==0) {cout<<"0"<<endl;continue;}
if(now==0){
int G=GCD(b,2*a);
b/=G,a=a*2/G;
if(a==1) cout<<-b<<endl;
else if((a<0&&b<0)||(a>0&&b>0)) cout<<"-"<<abs(b)<<"/"<<abs(a)<<endl;
else{
if(a<0) cout<<b<<"/"<<abs(a)<<endl;
else cout<<abs(b)<<"/"<<a<<endl;
}
}
else{
// cout<<now<<endl;
int lst=a;
int predis=1;
for(int i=1;i<=num;i++){
// if(now%(Prime[i]*Prime[i])==0) predis*=Prime[i],now/=Prime
int lsst=1,Q=0;
while(now%(lsst*Prime[i])==0) lsst*=Prime[i],Q++;
if(Q%2!=0) Q--;
predis*=Quickpow(Prime[i],Q/2),now/=Quickpow(Prime[i],Q);
if(now<Prime[i]) break;
}
if(now==1){
a=a*2;
int pre1=-b+predis,pre2=-b-predis,ch;
// cout<<pre1<<" "<<pre2<<endl;
if(a<0){
if(pre1>=0&&pre2<0) ch=pre2;
else if(pre1<0&&pre2>=0) ch=pre1;
else if(pre1>=0&&pre2>=0) ch=min(pre1,pre2);
else ch=min(pre1,pre2);
}
else{
if(pre1>0&&pre2<=0) ch=pre1;
else if(pre1<=0&&pre2>0) ch=pre2;
else if(pre1>=0&&pre2>=0) ch=max(pre1,pre2);
else ch=max(pre1,pre2);
}
// cout<<ch<<" "<<a<<endl;
int g=GCD(ch,a);
if(ch==0) {cout<<0<<endl;continue;}
ch/=g,a/=g;
if(a==1) cout<<ch<<endl;
else if((a<0&&ch<0)||(a>0&&ch>0)) cout<<abs(ch)<<"/"<<abs(a)<<endl;
else{
if(a<0) cout<<"-"<<ch<<"/"<<abs(a)<<endl;
else cout<<"-"<<abs(ch)<<"/"<<a<<endl;
}
continue;
}
if(b!=0){
int G=GCD(b,2*a);
b=b/G,a=a*2/G;
if(a==1) cout<<-b<<"+";
else if((a<0&&b<0)||(a>0&&b>0)) cout<<"-"<<abs(b)<<"/"<<abs(a)<<"+";
else{
if(a<0) cout<<b<<"/"<<abs(a)<<"+";
else cout<<abs(b)<<"/"<<a<<"+";
}
}
a=lst;
int G=GCD(a*2,predis);
predis/=G,a=a*2/G;
a=abs(a),predis=abs(predis);
if(predis==1){
if(a==1) cout<<"sqrt("<<now<<")"<<endl;
else cout<<"sqrt("<<now<<")"<<"/",cout<<abs(a)<<endl;
}
else{
if(a==1) cout<<abs(predis)<<"*"<<"sqrt("<<now<<")"<<endl;
else{
cout<<predis;
cout<<"*"<<"sqrt("<<now<<")"<<"/";
cout<<a<<endl;
}
}
}
}
}
/*
9 1000
1 0 -432
1 -3 1
2 -4 1
1 7 1
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?