根据《算法竞赛进阶指南》修改整理。
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]);
}