基础算法模板

根据《算法竞赛进阶指南》修改整理。

1.快速幂

int qp(int a,int b,int p)
{
    int res=1;
    while(b){
        if(b&1) res=1ll*res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res%p;
}

 2.64位整数乘法

求a*b%p

LL mul(LL a,LL b,LL p)
{
    LL res=0;
    while(b){
        if(b&1) res=(res+a)%p;
        a=a*2%p;
        b>>=1;
    }
    return res%p;
}

 方法2:

typedef long long LL;
typedef unsigned long long ULL;
typedef long double db;
ULL mul(ULL a,ULL b,ULL p)
{
    a%=p,b%=p;
    ULL c=(db)a*b/p;
    ULL x=a*b,y=c*p;
    LL ans=(LL)(x%p)-(LL)(y%p);
    if(ans<0) ans+=p;
    return ans;
}

3.二分

(1)整数集合上的二分

求递增序列a中>=x中的数最小的数

while(l<r){
	int mid=(l+r)>>1;
	if(a[mid]>=x) r=mid; else l=mid+1;
}
return a[l];

求递增序列a中<=x中的数最最大的数

while(l<r){
	int mid=(l+r+1)>>1;
	if(a[mid]<=x) l=mid; else r=mid-1;
}
return a[l];

(l+r)>>1不会取到r这个值;(l+r+1)>>1不会取到l这个值。

(2)在实数域上二分

确定精度:

#define rep(i,a,b) for (register int i=a;i<b;++i)
#define db double
#define eps 1e-5
while(l+eps<r){
	db mid=(l+r)/2;
	if(calc(mid)) r=mid; else l=mid;
}

不确定精度:

#define rep(i,a,b) for (register int i=a;i<b;++i)
#define db double
#define eps 1e-5
rep(i,0,100){
	db mid=(l+r)/2;
	if(calc(mid)) r=mid; else l=mid;
}

 4.离散化

数组版本

#define rep(i,a,b) for (register int i=a;i<b;++i)
void discrete()
{
	sort(a+1,a+n+1);
	rep(i,1,n+1) if(i==1||a[i]!=a[i-1]) b[++m]=a[i];
}
int query(int x)
{
	return lower_bound(b+1,b+m+1,x)-b;
}

vector版本

/*a为待处理离散化数据*/
#define rep(i,a,b) for (register int i=a;i<b;++i)
vector<int>v; 
void discrete()
{
	rep(i,0,n) v.push_back(a[i]);
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
}
int query(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin();
}

 map版本

/*a为带处理离散化数据*/
#define rep(i,a,b) for (register int i=a;i<b;++i)
map<int,int>mp;
int idx;
void ins(int x)
{
	if(!mp.count(x)) mp[x]=++idx;
}
void discrete()
{
	rep(i,0,n) ins(a[i]);
}
int query(int x)
{
	return mp[x];
}

 5.逆序对

分治求逆序对个数

#define rep(i,a,b) for (register int i=a;i<b;++i)
void merge(int l,int mid,int r) //合并a[l~mid],a[mid+1~r] 
{
	int i=l,j=mid+1;
	rep(k,l,r+1)
		if(j>r||i<=mid&&a[i]<=a[j]) b[k]=a[i++];
		else b[k]=a[j++],cnt+=mid-i+1;
	rep(k,l,r+1) a[k]=b[k];
}

6.st算法

rmq问题:

#define rep(i,a,b) for (register int i=a;i<b;++i)
void ST_prework()
{
	rep(i,1,n+1) f[i][0]=a[i];
	int t=log(n)/log(2)+1;
	rep(j,1,t) rep(i,1,n-(1<<j)+2) f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]); 
}
int ST_query(int l,int r)
{
	int k=log(r-l+1)/log(2);
	return max(f[l][k],f[r-(1<<k)+1][k]);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值