CHAPTER_4 算法初步入门
4.5.3 快速幂
题目:
给定三个正整数a、b、m(a<10^9,b<10^18,1<m<10^9),求 。
思路:
这里采用快速幂的思想(又称二分幂)。快速幂基于以下事实:
(1)若b为奇数,则有 。
(2)若b为偶数,则有 。
显然,b是奇数的情况总可以在下一步转换为b是偶数的情况,而b是偶数的情况总可以在下一步转换为b/2的情况。这样在log(b)级别次数的转换后,可以把b变为0.

参考代码:
typedef long long LL;
LL b_pow(LL a,LL b,LL m) {
if(b==0)
return 1; //a^0=1
if(b%2)
return a*b_pow(a,b-1,m)%m; //b为奇,计算a^b-1
else
return return b_pow(a,b/2,m)*b_pow(a,b/2,m)%m; //b为偶,计算a^b/2
}
4.6.1 two pointers
two pointers是一种思想。利用问题和序列的特性,使用两个下标i,j对序列进行扫描(可以同向扫描,可以反向),以较低的复杂度(一般是O(n))解决问题。
题目:
假设有两个递增序列A与B,要求将他们合并为一个递增序列C。
如:A={1,2,5},B={2,4,6},合并后 C={1,2,2,4,5,6}。
思路:
设置两个下标i,j,初值都为0,分别表示指向A和B的第一个元素。依次向右移动,根据A[i]和B[j]的大小决定哪个放入C中。
(1)若A[i]<B[j],则表示当前所剩元素中A[i]最小(因为元素递增,后面元素的必定比它大)。将A[i]放入C中,同时i++向右移一位。
(2)若A[i]>B[j],则表示当前所剩元素中B[i]最小(同理,后面元素的必定比它大)。将B[i]放入C中,同时j++向右移一位。
(3)若A[i]=B[j],则任选一个加入C,并让对应下标加1。
参考代码:
int merge(int a[],int b[],int *c,int n,int m) { //c为合并后数组的首地址,m和n为a序列和b序列的长度
int i=0,j=0,count=0;
while(i<n&&j<m) {
if(a[i]<=b[j]) {
c[count++]=a[i];
i++;
}
else {
c[count++]=b[j];
j++;
}
} //按上述思路依次判断并移动元素,当a和b序列有一个遍历完时退出循环
while(i<n) {
c[count++]=a[i];
i++;
} //如果a序列有剩余,则全部加入c
while(j<m) {
c[count++]=b[j];
j++;
} //如果b序列有剩余,则全部加入c
return count;
}
本文介绍快速幂算法及其实现,用于高效计算大数的幂次方,并通过模运算解决溢出问题。此外,还讲解了双指针技巧,演示如何合并两个有序数组,实现高效的数据处理。
1万+

被折叠的 条评论
为什么被折叠?



