必备的数学知识
对于
加法有(a+b)%c=((a%c)+(b%c))%c
则乘法也有(ab)%c=((a%c)(b%c))%c
//可以代入数去实验
问题引入
我们用程序去计算2的3次方显然等于8,但2的1000次方呢,显然结果是越界,编译器器会报错或输出一个0
对于大数运算,外面采用快速幂的方式进行降低时间复杂度的运算
例如计算2的n次方并对2019取模的值(n可以取大数)
1. 递归法
核心递归式
a的n次方对c取余
1.为奇数时=a*(a的n-1次方)%c;=(a%c*(a的n-1次方)%c)%c
2.为偶数时=(a的n/2次方)*(a的n/2次方)%c
代码实现
public class fushumi {
public static void main(String[] args) {
//计算a的n次方再对c取余
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();//计算n次方
long c=scanner.nextLong();//结果所需取的余数
long res=qp(2,n,c);
System.out.println(res);
}
public static long qp(int a,long n,long c){
if (n==1){//递归出口
return a%c;
}
if ((n&1)==1){//指数为奇数
return (a%c*qp(a,n-1,c)%c)%c;
}else{//指数为偶数
long mid=qp(a,n/2,c)%c;
return mid*mid;
}
}
}
2. 非递归实现(扩大底数法)
核心递推式
a^n=a*a^(n-1);//奇数
a^n=(a*a)^(n/2);//偶数
代码实现
public class fushumi {
public static void main(String[] args) {
//计算a的n次方再对c取余
//非递归实现
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();//计算n次方
int ans=1;
long a=2;//求2的n次方
long c=scanner.nextLong();//结果所需取的余数
while (n>0){//指数为奇数
if ((n&1)==1){
ans*=a%c;
n--;//指数减一变为偶数
}
a%=c;
a=(a*a)%c;//底数翻倍,
n>>=1;//指数减半
}
System.out.println(a);
}
}
此处递推式以指数形式增加
a=(a*a)%c;//底数以指数形式翻倍