优化,还是不优化,这是个问题


  本讨论仅基于程序基本上正确的情况下。

(一)第一次作业

  众所周知,本次作业没有优化到100分的都进入了B组或者C组,所以事实上本次作业的优化是十分简单的,在这里提几句。

  (1)合并同类项

  最简单的做法也是最高效的做法,通过Hashmap,将指数存为key,将系数作为对应value,那么可以很简单的将同类项进行合并。

  (2)对项进行省略

  当然,+0,0*,1*,等这样无意义的项,仅需要做特殊判断,那么就可以直接省略,从而缩减表达式的长度。

  (3)对项进行排序

  对于负数,会比正数多一个不必要的符号,所以我们可以直接将负号作为减号放到项中,所以最好的做法是对所有在Hashmap里的系数做一个判断,先输出正项,若无正项,则输出负项。

  经过以上三种处理,第一次作业便可以完美的将表达式化简为最简形式。

(二)第二次作业

  本部分是本次讨论的重点部分。

  第二次作业开始,大家的算法实现就变得五花八门,面向过程的,面向对象的,不一而足。

  所以在这里我要基于一个看起来似乎是解决本次作业最好的算法来讨论化简。

  根据题目可以得知,每一个原子项可以写成如下形式(请原谅我的超长正则):

(([+-]{0,3}\\d+)|([+-]{0,2}x(\\^[+-]?\\d+)?)|([+-]{0,2}sin\\(x\\)(\\^[+-]?\\d+)?)|([+-]{0,2}cos\\(x\\)(\\^[+-]?\\d+)?))(\\*(([+-]?\\d+)|(x(\\^[+-]?\\d+)?)|(sin\\(x\\)(\\^[+-]?\\d+)?)|(cos\\(x\\)(\\^[+-]?\\d+)?)))*

  所以首先应该做的是对于原子项中的因子合并,从而形成形如a*x^b*sin(x)^c*cos(x)^d的形式,进而大大缩短了处理难度,下面放出我的合并函数:

  

for (String it : ob) {
if (it.matches("[+\\-]?\\d+")) {
num = num.multiply(new BigInteger(it));
}
else if (it.matches("[+-]?sin\\(x\\)(\\^[+-]?\\d+)?")) {
if (it.substring(0, 1).matches("-")) {
num = num.multiply(new BigInteger("-1"));
}
sin = "sin(x)^" + combine(sin, it);
}
else if (it.matches("[+-]?cos\\(x\\)(\\^[+-]?\\d+)?")) {
if (it.substring(0, 1).matches("-")) {
num = num.multiply(new BigInteger("-1"));
}
cos = "cos(x)^" + combine(cos, it);
}
else if (it.matches("[+-]?x(\\^[+-]?\\d+)?")) {
if (it.substring(0, 1).matches("-")) {
num = num.multiply(new BigInteger("-1"));
}
x = "x^" + combine(x, it);
}
}
private String combine(String sss, String it) {
Pattern p = Pattern.compile("\\^");
Matcher m = p.matcher(it);
BigInteger b1;
BigInteger b2;
if (sss.equals("")) {
if (m.find()) {
String t = it.substring(m.start() + 1);
return t;
}
else {
return "1";
}
}
else {
Pattern pp = Pattern.compile("\\^");
Matcher mm = pp.matcher(sss);
if (mm.find()) {
b1 = new BigInteger(sss.substring(mm.start() + 1));
if (m.find()) {
b2 = new BigInteger(it.substring(m.start() + 1));
}
else {
b2 = new BigInteger("1");
}
b1 = b1.add(b2);
return b1.toString();
}
}
return "0";
}

  便将每一原子项中的同类因子合并,之后应该在项内做排序,从而得出如上述规范化的式子,即a*x^b*sin(x)^c*cos(x)^d的形式,这里就省略排序代码。

  将通过+-分隔的每一原子项按照如上规则处理好之后,可以进行存入Hashmap处理,处理方式如下:

  设立Poly类,其中包含BigInteger参数三个,分别为b、c、d,即x,sin(x),cos(x)各自的指数(若不存在此因子则指数为0),那么可以将此三元组作为key值,将a,即系数作为value,形成一个新的Hashmap,形式为Hashmap<Poly, BigInteger>,可知,对每个相同形式的项,均可以用前述方法处理并合并为同类项。

  对于三角函数化简公式,比较简单的有如下几种:

sin(x)^2 + cos(x)^2 = 1
1 - cos(x)^2 = sin(x)^2
1 - sin(x)^2 = cos(x)^2

  进阶版的有如下形式:

sin(x)^4 + 2 * sin(x) ^2* cos(x)^2 + cos(x)^4 = 1
sin(x)^4 - cos(x)^4 = sin(x)^2 - cos(x)^2
......

  事实上,若想比较好的化简,应该先将进阶版部分的三角函数进行化简(即降次,否则会导致需要重复使用基础版化简公式,导致TLE)

  由于我们的存储方式,可以知道,对于进阶版化简部分,可以枚举出几个典型的公式,进行if-else判断(方法繁琐但不容易出错),将常见的进阶版公式化简之后,就可以愉快的开始基础版化简了。

·      而根据我们之前所讨论的Hashmap存储方法,可知两对三元组为<b1, c1, d2>、<b2, c2, d2>,若满足:

1.b1 == b2
2.(abs(c1 - c2) == 2 && d1 == d2) || (abs(d2 - d1) == 2 && c1 == c2)

3.b1 == b2
2.(c1 - c2 == 2 && d1 - d2 == -2) || (d2 - d1 == 2 && c1 - c2 == -2)

  即可将含有基础版化简形式的部分项化简,若分别考虑两者系数a1, a2,则会保留下某一三元组的部分式子。而上述基础版化简的时候要记得用if-else判断为哪种形式,否则化简出来的式子会含有^0之类不应该存在的部分。

  在化简的时候需要注意的是,在Hashmap存化简之后的项的时候,要用keycontains检测是否已经存在了项,不要将已有的项覆盖掉:)

  最后处理按照第一次作业类似的方法(排序,正项提前等)即可将化简做到比较好的程度。

(三)第三次作业

  具体请见作业博客,网址如下:

https://www.cnblogs.com/dxy1999/p/10585219.html

  最后, 我想说,其实化简表达式并不完全是为了分数,而更应该从中学到如何将OO课程学的更好。试问,如果在化简的时候对于自己的类的概念不清晰,又怎能写出正确的代码呢?疯狂面向过程写代码,又会创造出多么长的代码呢?愿我们共勉。


简,你化不化,它就在那里

buaaoo_first_improvement的更多相关文章

随机推荐

  1. 【XSY3344】连续段 DP 牛顿迭代 NTT

    题目大意 对于一个长度为 \(n\) 的排列 \(p\),我们称一个区间 \([l,r]\) 是连续的当且仅当 \((\max_{l\leq i\leq r}a_i)-(\min_{l\leq i\l ...

  2. 使用lambda表达式对相同属性的实体进行合并

    List<CrmAuthorizedInfo> crmAuthorizedInfos = flowPlanInfoMapper.findAllByEncode(stationForm.ge ...

  3. 数论ex

    数论ex 数学学得太差了补补知识点or复习 Miller-Rabin 和 Pollard Rho Miller-Rabin 前置知识: 费马小定理 \[ a^{p-1}\equiv 1\pmod p, ...

  4. GWAS群体分层校正,该选用多少个PCA

    前言 关于选用多少个PCA做群体分层校正,各大期刊并没有一个统一的说法. 故做了如下综述. 1 随心所欲型,想选多少就选多少 PCA想选多少就选多少,这个真的不是开玩笑.有文献出处有真相! 比如下面文 ...

  5. MyISAM与InnoDB的区别是什么?

    1. 存储结构 MyISAM:每个MyISAM在磁盘上存储成三个文件.第一个文件的名字以表的名字开始,扩展名指出文件类型..frm文件存储表定义.数据文件的扩展名为.MYD (MYData).索引文件 ...

  6. QMQTT简单介绍(1)

    1 准备工具: wireshark安装包:网络抓包工具qmqtt源码:mqtt客户端源码(Qt版本)官网:http://mqtt.org/英文版协议说明文档:http://docs.oasis-ope ...

  7. 第31月第25天 xcode debug 限制uitextfiled输入

    1.xcode debug 了解了每个设置的意思,个人觉得对于一个普通的app来说可以这样配置这些设置: Generate Debug Symbols:DEBUG和RELEASE下均设为YES(和Xc ...

  8. 微信小程序常见的坑

    wxml的标签跟html里面的一些标签是一样的,比如view标签相当于div标签,text标签相当于span标签. 在微信小程序中,表单元素都是原生组件,微信小程序中原生组件层级最高,所以在用inpu ...

  9. 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史(转载)

    转载 https://zhuanlan.zhihu.com/p/49271699 首发于深度学习前沿笔记 写文章   从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 张 ...

  10. 有关mysql索引

    1.首先我们需要明确一下什么是索引以及为什么要使用索引: 索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构.在生产环境中,对于数据库我们最常进行的是查询的操作,而当我们的数据非 ...