快速幂&快速乘法
对于快速幂,举个例子:求2024^2024,结果对1e9+7取模?
此时如果你直接调用Math.pow(),肯定是算不出来的;
- 原因1:数据实在太大了,double也装不下,虽然结果是对1e9+7取模,但是这个Math.pow()毕竟是库里的函数,只能给数据出结果。无法在过程上进行取模,这也是快速幂诞生的一个原因,使得我们能在过程上稍加修改。
- 原因2:将2024乘2024次肯定会超时。
通过上述两点原因,体现了快速幂的重要性。
快速幂
举一个简单的例子:计算3^11,普通的方法就不必多说了,就是将3乘11次。快速幂的算法:将11的二进制拿出来->(1011)
- 规律
- 根据二进制是否为1来判断是否将该位乘进去
- 从右往左看第二个圈的那几个数字,分别是前一个数字的平方。
快速乘法
其实知道了快速幂就相当于也学会了快速乘法,也是同样的推导歩奏,只是需要将乘法换成加法就行了。
package Month1;
/**
* 掌握快速幂算法:
*
* @author 逍遥
*
*/
public class Demo231110 {
static long MOD = (long)(1e9+7);
public static void main(String[] args) {
long ret = quickPow(2024,2024);
System.out.println(ret);
long ret2 = quickMultiply(23,23);
System.out.println(ret2);
long ret5 = quickMultiplyBit(23,23);
System.out.println(ret5);
long ret3 = quickPowBit(2024,2024);
System.out.println(ret3);
long ret4 = quickPow2(2024,2024);
System.out.println(ret4);
}
//快速乘法,MOD
public static long quickMultiply2(long base,long power) {
long ret =0;
while(power !=0) {
if(power%2 ==1)ret=(ret+base)%MOD;
base=(base+base)%MOD;
power/=2;
}
return ret;
}
//快速幂,MOD
public static long quickPow2(long base,long power) {
long ret =1;
while(power !=0) {
if(power%2 ==1)ret=quickMultiply2(ret,base)%MOD;
base=(base*base)%MOD;
power/=2;
}
return ret;
}
//快速乘法(用于算很大的数相乘,但是避免过程中越界),可以直接将快速幂的*改成+,ret =0
public static long quickMultiply(long base,long power) {
long ret =0;
while(power !=0) {
if(power%2 ==1)ret+=base;
base+=base;
power/=2;
}
return ret;
}
//快速幂
public static long quickPow(long base,long power) {
long ret =1;
while(power !=0) {
if(power%2 ==1)ret*=base;
base*=base;
power/=2;
}
return ret;
}
//快速幂(二进制)
public static long quickPowBit(long base,long power) {
long ret =1;
while(power !=0) {
if((power &1) == 1) ret=(ret*base)%MOD;
base=(base*base)%MOD;
power>>=1;
}
return ret;
}
//快速乘法(二进制)
public static long quickMultiplyBit(long base,long power) {
long ret = 0;
while(power !=0) {
if((power & 1) == 1) ret= (base+ret)%MOD;
base= (base+base)%MOD;
power >>=1;
}
return ret;
}
}
最大公因数&最小公倍数
最大公因数
最大公因数的定义想必大家都知道,这里简单提一嘴:
对于a,b;a和b的最大公因数就是他们拥有的公共因数里最大的那一个。
//最大公因数:
public static int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
最小公倍数
就是两个数的乘积再除以最大公因数:a*b/gcd(a,b);
//最小公倍数:
public static int lcm(int a,int b) {
return a*b/gcd(a,b);
}