快速计算高精乘低精---低精优化高精

这是一个普通人都想得出来的超简单但很有用的优化。

                                                                    -----序言

​ 给一个题:

​ 计算n!的阶乘,n<=10000,时限500ms。

一.各种算法
​ 要是你打普通高精乘低精,辣么恭喜您GG,要是您不爽时限,给他加大成1000ms,恭喜您,还是GG。

​ 于是,您就可以光荣的放弃打普通高精乘低精的想法,于是您注意到,当n=10000时,2s还是跑得动的。

​ 于是,您决定打表...然鹅,毒瘤的题中,当n=10000时,|ans|=35660,然后。。。打表GG。

​ 于是您又灵机一动,决定分块打表。您发现,n=1000时,500ms可以轻松跑动,于是就诞生了此题的分块打表法:打表出n=1000,2000,3000,4000,5000,6000,7000,8000,9000,10000共10个表,然后对数据分类讨论,计算该数据所属区间,然后进行0-999次高精乘低精就可以解决此题了。而且,10个表的长度和也在接受范围(感觉不好看的可以进行加长或者不打10000的表)。然后您就顺利的AC了此题了,可喜可贺!

​ 然后,您思考,这样做法虽然可以完美解决此题,不过,要是n的范围再大一点,就不好办了,于是您开始考虑更加靠谱的做法...

二.低替高优化
​ 我们先来考虑n很小的情况,比如,当n=20的时候,我们真的有必要使用高精吗?我们肯定开个long long就跑啊!可以知道,这样我们用20次O(1)的低精代替了20次O(n)的高精,时间效率大大优化,然而,这只是对于n很小,当n取到100(其实要不了100)。。。连int128也不能承受了。哪怕int128可以承受100,对整体10000次高精的优化其实并不大。

​ 但,我们从上面的例子可以得出:如果当前乘法可以用低精代替,我们就可以使用低精!有了这个思想后,我们开始低替高优化,我们知道,这个优化中,高精乘法是大爷,所以我们要想方设法减少高精次数,即,能用低精就用低精,不能用才用高精,于是,我们设定一个值maxe,表示我们使用低精的极限(建议:不用开太大,因为高精时可能造成低精数*9的情况,所以建议开类型范围的0.1倍(好像高一点也行)),然后,我们就开始乘法,这里假设我们要乘以一个A,我们有一个高精数ans表示答案,一个低精数ant(ans,ant初始皆为1),那么我们分为两种情况:

1.maxe/A>=ant(为什么不写成maxe<A**ant呢?因为可能爆范围)
​ 这时,咱们的大爷高精发现小弟低精可以解决这个小怪,于是,就让小弟低精解决就好了,所以这时,我们令:ant=ant*A,即可

2.maxe/A<ant
​ 这时,大爷高精,发现低精打不赢了,于是,他叹口气,将小弟低精的hp恢复满再去打这个小怪,即:

​ ans=ans*ant(这里用了重载,你只需要知道,ans的乘法都是高精就好了)

​ ant=A(现在小弟低精可以打怪了)

​ 然后,进行所有的乘法即可。

​ 最后,由于大爷要解决所有的小怪,而小弟还没解决完,所以,大爷大袖一挥:

​ ans=ans*ant

​ ant=1(看情况而定,不写也行)

​ 此时ans即为答案,完。

至于速度,肯定是能500ms过10000!的阶乘的啊!(想要追求更快的速度,可以加个分块打表)(滑稽)

posted @ 2019-01-12 17:20  ThinkofBlank  阅读(636)  评论(1编辑  收藏  举报