《算法笔记》读书记录DAY_6

本文介绍快速幂算法及其实现,用于高效计算大数的幂次方,并通过模运算解决溢出问题。此外,还讲解了双指针技巧,演示如何合并两个有序数组,实现高效的数据处理。

CHAPTER_4  算法初步入门

4.5.3 快速幂

题目:

给定三个正整数a、b、m(a<10^9,b<10^18,1<m<10^9),求 a^{b}%m

思路:

这里采用快速幂的思想(又称二分幂)。快速幂基于以下事实:

(1)若b为奇数,则有 a^{b}=a*a^{b-1}

(2)若b为偶数,则有 a^{b}=a^{b/2}*a^{b/2}

显然,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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值