当你瞧见n^m的时候,你会想,不就是n的m次方不?当然,学过数学你就不会惊慌,你会很淡然地暗示自己敲击键盘就OK了- -!然后,当你看见m<100...000的时候,你也会淡然地停止你运动的手指,为啥?以后你发现自己去厕所拉屎回来了这代码都还没运行完,怎么办?OK!你赚了,正好我教你一种神一般超然存在的算法---------快速幂取模
亲,对于有好多巴多个n相乘的问题,你爆菊花去暴力是会超时的,快速幂取模就是为了解决他而出现的,也不知道是谁发明的,学会之后我就想大喊“哟,怎么这么好用!!”
快速幂取模应用到的是位运算的概念,我是这么想的,虽然不知道什么是位运算- -!但是意思就是这样,一位一位来考虑
直接上例子吧,爽快点,直接求2^8
我把它摊开变成了2x2x2x2x2x2x2x2,一个2就是一位,现在有8位?懂?别讨骂- -!
然后我就两两合成,变成4x4x4x4,这个能懂?把两位计算出来,结果就是新的一个位,这是有4个位
再合成就是16x16,再合成就是256,这时的256难道不是结果?小学生都知道的哦,亲!
这是总的思想,然后看具体实现,这时8次幂不经典,就2^15吧!
2^15——>4^7x2——>16^3x4x2——>256^1x16x4x2,不知道亲爱的你看出规律了没?
只有偶数次幂是可以合成的,懂?出现奇数次了肿么办?- -!蠢啊?上面不是表现出来了么?直接提取一次幂撒,嘿嘿,提取出来的就直接乘到记录总结果的变量里面去,这样就一个都没落下了
直接上个小模版吧,这个是我写惯了的
int q_mod(int a,int b,int mod) //幂取模幂取模,就是因为结果太大了才要取模,这里是(a^b)%mod
{
int s=1; //求的是积而不是和
while(b>0) //大于0是为了一次幂的时候直接加进去
{
if(b%2==1) //表示当前是奇数次幂
{ s=s*a%mod;b/=2; } //合成时把多出来的一次放进s,并且b要减半
a=a*a%mod; //合成都是把位变成a*a
} //每次都要取模,因为不知道计算结果会不会太大而过界
快速幂取模怎么样?有木有不懂的?要不要我弄一个例题来体现你这战斗力不足0.1的渣渣的智商啊?- -!根据我上面那两个例子加上我这个模版和上面的解释,NTM还不懂那你听我唱征服算了-----