暑期集训(4) 二分(与快速幂)

14 篇文章 0 订阅
12 篇文章 0 订阅

_φ(❐_❐✧ 二分与快速幂

1.二分概念

1).官方解释

一维数组的查找操作,就是在一维数组中查找有没有某个元素,它的值等于指定的值 x。查找操作的结果可能是一个没找到、找到一个或者找到很多个。常见的查找算法有“顺序”查找和“二分”查找。
顺序查找就是按照从前往后的顺序,将数组中的元素依次与要查找的数 x 进行比较。
二分查找又称“折半”查找,其优点是比较次数少、查找速度快。但是要求数据是递增或递减排序的。

2).个人理解

二分查找:改变边界信息,在有序的情况下节省了大量时间+

二分排序:二分通过对半排序,左右融合,在没有序的情况下时间复杂度略小于sort,是绝对的 n*log(n),但其实实用性不大,多用于求逆序对,见下例题

2.二分模板如下

int left = 0,right = n - 1; 
int find = n;//find标记找到的位置,初始化为n,表示没找到
while(left <= right){
	int mid = (left + right) / 2;
	if(a[mid] == x){//找到了,就标记位置,并退出循环
			find = mid;
			break;
	}
	if(x < a[mid]) right = mid - 1;//x只能在左半部分
	if(a[mid] < x) left = mid + 1; //x只能在右半部分
}
if(find != n) printf("%d\n",find);
else printf("not find\n");

3.二分例题(附带快速幂)

《1》.A的B次方(快速幂裸题)
<1>思路

求解a的b次方,for循环一个个算是超时的
所以用数学的方法推论
a的b次方
当b为0时,直接返回1即可
当b为偶数时
就例如2的4次方,详见七上的数学第一章
等于4的2次方
就例如这样,可以用while循环或dfs写
b为奇数时,直接指数减一再反乘系数即可
记得每次%数据

<2>快速幂写法与代码
long long s=1;
	while(b)
	{
		if(b%2==1)  s=(s%mod*a%mod)%mod;
		b=b/2;
		a=(a%mod*a%mod)%mod;
	}
	return s;
int dfs(long long p,long long q)
{

    if (q==0)               return 1;
    else if (q%2==1)        return dfs(p,q-1)*p%m;
    else
    {
        long long cnt=dfs(p,q/2)%m;
        return cnt*cnt%m;
    }
}
《2》.逆序对统计

在这里插入图片描述

<1>.思路

没有什么好说的,使用归并排序每一次交换记录逆序对
分成两份排序,交换;再融合与交换

<2>.代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int a[maxn],c[maxn];
long long cnt=0;
void work(int l,int r)
{
	int mid,tmp,i,j;
	if(r>l+1)
	{
		mid=(l+r)/2;
		work(l,mid-1);
		work(mid,r);
		tmp=l;
		for(i=l,j=mid;i<=mid-1&&j<=r;) 
		{
			if(a[i]>a[j])
			{
				c[tmp++]=a[j++];
//				tmp; j;
				cnt+=mid-i;
			}
			else c[tmp++]=a[i++];
		}
		if(j<=r) for(;j<=r;j++) c[tmp++]=a[j];
		else for(;i<=mid-1;i++) c[tmp++]=a[i];
		for(i=l;i<=r;i++) a[i]=c[i];
	}
	else
	{
		
		if(a[l]>a[r])
		{
			swap(a[l],a[r]);
			cnt++;
		}
	}
}
int main()
{
	freopen("deseq.in","r",stdin);
	freopen("deseq.out","w",stdout);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	work(1,n);
	cout<<cnt;
	return 0;
 }
《3》.越狱(数论+快速幂)在这里插入图片描述
<1>.思路

看到题目,想到顺推犯人的位置
但前后影响太大
于是逆推总可能情况-两者不相连情况
相减注意负数情况即可
那怎么做出这两个数据呢
这就需要数论实现
每个人都可能在一个位置
所以总情况为m的n次方
那不可能的情况就想小学做的染色问题
是m-1的n-1次方,因为旁边的宗教与自己的宗教不相同
最后快速幂求解取%即可

<2>.代码实现
long long f(long long a,long long b)
{
	long long s=1;
	while(b)
	{
		if(b%2==1)  s=(s%mod*a%mod)%mod;
		b=b/2;
		a=(a%mod*a%mod)%mod;
	}
	return s;
}
int main()
{
	freopen("prison.in","r",stdin);
	freopen("prison.out","w",stdout);
	cin>>m>>n;
	x=f(m,n)%mod;
	y=m*f(m-1,n-1)%mod;
	
	cout<<(x-y+mod)%mod;
	return 0;
} 

总结

总之,二分重在实用,可以与多种形式的题目与算法结合,真正的理解和写出二分大有益于代码的学习与码出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值