常见算法的拓展

  • Floyed--最小环

题目链接

思路:枚举环上一条路径 ij,那么该环一定由是一条 ki 的边和该路径再加 jk 的边。在取最小值时要判 ij

code:

点击查看代码
int n,m,ans=inf/10,e[107][107],dis[107][107];
void solve(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			e[i][j]=dis[i][j]=inf/10;
		}
	}
	for(int i=1,u,v,w;i<=m;i++){
		scanf("%d%d%d",&u,&v,&w);
		e[u][v]=e[v][u]=dis[u][v]=dis[v][u]=w;
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i^j)ans=min(ans,dis[i][j]+e[k][i]+e[j][k]);
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
			}
		}
	}
	if(ans==inf/10)printf("No solution.");
	else printf("%d",ans);
}
  • 埃筛--区间筛

题目链接

思路:若 n 为合数,那么他的最小质因子 n。筛出 [1,n] 中的所有质数,再对要求范围内的所有数进行埃筛即可。

code:

点击查看代码
int n,m,k,ans,pm[maxn];
bool vis[maxn];
void solve(){
	const int mxn=1<<16;
	for(int i=2;i<=mxn;i++){
		if(!vis[i])pm[++k]=i;
		for(int j=1;j<=k&&pm[j]<=mxn/i;j++){
			vis[i*pm[j]]=true;
			if(i%pm[j]==0)break;
		}
	}
	scanf("%lld%lld",&n,&m);
	mems(vis,false);
	for(int i=1;pm[i]*pm[i]<=m;i++){
		for(int j=(max(2ll,(n-1)/pm[i]+1))*pm[i];j<=m;j+=pm[i]){
			vis[j-n+1]=true;
		}
	}
	for(int i=1;i<=m-n+1;i++)ans+=!vis[i];
	printf("%lld",n==1?ans-1:ans);
}
  • 矩阵乘法+Floyed--倍增Floyed

题目链接

思路:ij 经过 x+y 条边的最短路等于对于每个 k 点,ik 的最短路加上 kj 的最短路的最小值。

code:

点击查看代码
int n,m,s,t,tot,bk[1007];
struct matrix{
	int e[maxn][maxn];
	matrix operator*(const matrix x)const{
		matrix res;
		for(int i=1;i<=tot;i++){
			for(int j=1;j<=tot;j++){
				res.e[i][j]=inf/2;
				for(int k=1;k<=tot;k++){
					res.e[i][j]=min(res.e[i][j],e[i][k]+x.e[k][j]);
				}
			}
		}
		return res;
	}
}st;
matrix qpow(matrix x,int y){
	y--;matrix res=x;
	while(y){
		if(y&1)res=res*x;
		x=x*x;
		y>>=1;
	}
	return res;
}
void solve(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for(int i=1;i<=200;i++){
		for(int j=1;j<=200;j++){
			st.e[i][j]=inf/2;
		}
	}
	while(m--){
		int u,v,w;
		scanf("%d%d%d",&w,&u,&v);
		if(!bk[u])bk[u]=++tot;
		if(!bk[v])bk[v]=++tot;
		st.e[bk[u]][bk[v]]=st.e[bk[v]][bk[u]]=w;
	}
	matrix ans=qpow(st,n);
	printf("%d",ans.e[bk[s]][bk[t]]);
}
  • 树状数组——权值树状数组上倍增

先咕着,等找到合适的例题再补上。

  • 树状数组——离线处理

题目链接

思路:以右端点为关键字排序,通过记录已经出现过的种类实现去重,最后以前缀和的方式计算答案。

code:

点击查看代码
int n,m,d[maxn],lst[maxn],ans[maxn],e[maxn];
struct node{
	int l,r,id;
	bool operator<(const node &x)const{return r<x.r;}
}q[maxn];
inline int lowbit(int x){return x&(-x);}
void update(int x,int y){
	while(x<=n){
		e[x]+=y;
		x+=lowbit(x);
	}
}
int query(int x){
	int ret=0;
	while(x>0){
		ret+=e[x];
		x-=lowbit(x);
	}
	return ret;
signed main(){
	read(n);
	for(int i=1;i<=n;i++)read(d[i]);
	read(m);
	for(int i=1;i<=m;i++)read(q[i].l),read(q[i].r),q[i].id=i;
	sort(q+1,q+m+1);
	for(int i=1,now=1;i<=m;i++){
		while(now<=q[i].r){
			if(lst[d[now]])update(lst[d[now]],-1);
			lst[d[now]]=now;
			update(now++,1);
		}
		ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
	}
	for(int i=1;i<=m;i++)write(ans[i]);
}
posted @   yinhee  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示