题目链接:https://www.luogu.com.cn/problem/P1067
显然这道题是一道水题.但往往水题的解法可以看出解题人的水平.
在讨论之前,我们先看看此题的两种AC代码:
代码一:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string str="";
int n,m;
cin>>n;
m=n;
string a[n+1];
for(int i=0;i<m+1;i++)
cin>>a[i];
for(int j=0;j<m+1;j++){
stringstream ss;
ss<<n;
string sn=ss.str();
//首位!=0
if(j==0){//判断是否首位,进行首位下的逻辑
if(n!=0){
if(a[j]=="1") {//首位是否为1
if(sn!="1") str=str+"x^"+sn; //指数是否为1
else str=str+"x";
}
else if(a[j]=="-1"){
if(sn!="1") str=str+"-"+"x^"+sn;
else str=str+"-"+"x";
}
else{
if(sn!="1") str=str+a[j]+"x^"+sn;
else str=str+a[j]+"x";
}
}
else{
if(a[j]=="1") {
if(sn!="1") str=str+"x^"+sn;
else str=str+"x";
}
else if(a[j]=="-1"){
if(sn!="1") str=str+"-"+"x^"+sn;
else str=str+"-"+"x";
}
else str=str+a[j];
}
}
else if(a[j]=="0")
str+="";
else if(a[j]!="1"&&a[j]!="-1"){
if(a[j][0]!='-'){
if(n!=0){
if(sn!="1") str=str+"+"+a[j]+"x^"+sn;
else str=str+"+"+a[j]+"x";
}
else str=str+"+"+a[j];
}
else{
if(n!=0) {
if(sn!="1") str=str+a[j]+"x^"+sn;
else str=str+a[j]+"x";
}
else str=str+a[j];
}
}
else{ //if(a[j]=="1"&&a[j]=="-1"){
if(a[j][0]!='-'){
if(n!=0){
if(sn!="1") str=str+"+"+"x^"+sn;
else str=str+"+"+"x";
}
else str=str+"+"+a[j];
}
else{
if(n!=0) {
if(sn!="1") str=str+"-"+"x^"+sn;
else str=str+"-"+"x";
}
else str=str+a[j];
}
}
n--;
}
cout<<str;
return 0;
}
代码二:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a;
cin>>n;
for(int i=n;i>=0;i--){
cin>>a;
if(a){ 判0系数
if(i!=n&&a>0)cout<<"+"; 根据正负、是否为最高此项决定加号
if(abs(a)>1||i==0)cout<<a; 输出系数(系数不为正负1或指数为0)
if(a==-1&&i)cout<<"-"; -1系数特判,常数项已特判
if(i>1)cout<<"x^"<<i; 二次及以上输出指数
if(i==1)cout<<"x"; 一次项
}
}
}
简单的一看,我们大致就能看出高低了.
那么,为什么差别这么大呢?
其实就是解题者抽象思维差异.
在拿到一道题的时候,首先应该冷静的分析,用数学思维抽象出他的具体逻辑.越简单越好,最好是把他变为一个公式或者数学书中的定义概念一样.而不是着急着去写代码,那样写出来的代码即便能够AC,我想也是经过编译器不断的调试,然后对逻辑的不断补充和优化.最终得到的是一个打满补丁的程序,甚至最终遗憾离场.而不是一个从一开始就是思维逻辑的产物,可以经得住无数测试示例的狂轰乱炸.
那么,应该怎么办呢?
以此题为例:拿到题之后,三分钟时间不要去敲代码.
首先,去思考分析题意.
大致看一遍题之后,就能明白题意,根据输入的各种参数,输出一个一元n次多项式.(输出格式和数学表达式书写习惯一样).
一个多项式包含什么呢?无外乎三个,系数,元,指数.而此题有明确告诉是一元,所以就是x,且指数>0,系数!=0
知道了结构(也就是单项式)之后,应该在注意这三个东西组合成一个多项式的时候应该注意什么.也就是中间的符号衔接问题.
明显,如果是系数为负,则不用添加.若为正,因为人类的书写习惯正号省略,所以要填上正号+.
假设系数是a,指数是b.那么"一般"就是像aX^b这样的单项式通过正负号链接的组合
接着继续拆分,一项一项分析系数项和元和指数.
所以思维是:多项式--->单项式--->系数项和元和指数.
如果a=0,单项式为空.
如果a=正负1,则不用输出系数,但需考虑正负号
如果b=0,为常数项,只需输出系数
如果b=1,为一次项,只需输出元X
如果不是首项,且a>0.要填上+,最后一项(指数为0)只用输出系数a,中间项需要根据系数正负来判定加不加+.是正数就加.
如果系数的绝对值大于1,系数也要输出a
现在就可以写代码了.只需要把思维过程用代码表现出来.
cin>>n;n代表了这个多项式中单项式的个数,他又和指数有关
for(int i=n;i>=0;i--){ 指数从5开始到0结束,此处的i即为上面分析的b
cin>>a; 输入系数
if(a){ 判0系数,是0不输入
if(i!=n&&a>0)cout<<"+"; 不是首项,即中间项,则根据正负为此项决定加不加+号
if(abs(a)>1||i==0)cout<<a; 输出系数(系数不为正负1或指数为0)
if(a==-1&&i)cout<<"-"; -1系数特判且不为常数项(即指数不为0)
if(i>1)cout<<"x^"<<i; 二次及以上输出指数
if(i==1)cout<<"x"; 一次项
}
}