同余最短路

同余最短路#

题型#

  • 给定 n 个整数,求这 n 个整数能拼凑出多少的其他整数( n 个整数可以重复取)
  • 给定 n 个整数,求这 n 个整数不能拼凑出的最小(最大)的整数
  • 至少要拼几次才能拼出模 kp 的数

例题#

P3403 跳楼机#

题意

给定 x,y,z ,问对于 k[1,n] 有多少个 k 能满足 ax+by+cz=k (a,b,cN+)

思路

d(i) 表示仅通过操作 2,3 (a=0) 能达到的modx=i 的最小楼层

那么可得

d(i+y)=d(i)+y d(i+z)=d(i)+z

最短路的求法是:dis(x)=dis(y)+edge(x,y)

类比一下,让 i+yi+z 变成点,y,z 变成边权,通过跑最短路求得 d(1x1)

因为 1 操作可以每次让楼层加 x ,所以最后的答案就是

i=1x1hd(i)x+1

+1 因为算当前楼

注意尽量选较小的 x 当作模数,可以省时空复杂度

#include<bits/stdc++.h>
using namespace std;

#define pb push_back
#define mp make_pair
#define pii pair <int,int>
#define int long long

const int N=1e5+5;
const int inf=2e18;

inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}

int h,x,y,z,ans;
int d[N];
bool vis[N];
vector <pii> G[N];

inline void add(int a,int b,int c){
	G[a].pb(mp(b,c));
}

inline void SPFA(){
	queue <int> q;
	for(int i=0;i<N;++i) d[i]=inf;
	d[1]=1,vis[1]=1;
	q.push(1);
	while(!q.empty()){
		int u=q.front();q.pop();
		vis[u]=0;
		for(auto y:G[u]){
			int v=y.first,val=y.second;
			if(d[v]>d[u]+val){
				d[v]=d[u]+val;
				if(!vis[v]){
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
}

signed main(){
	h=read(),x=read(),y=read(),z=read();
	if(x>y) swap(x,y);
	if(x>z) swap(x,z);
	if(x==1||y==1||z==1){
		cout<<h<<endl;
		return 0;
	}
	for(int i=0;i<x;++i){
		add(i,(i+z)%x,z);
		add(i,(i+y)%x,y);
	}
	SPFA();
	for(int i=0;i<x;++i) if(h>=d[i]) ans+=(h-d[i])/x+1;
	cout<<ans;
}

P2371 墨墨的等式#

题意

给定 a[1n] ,问对于 k[l,r] 有多少个 k 能满足 i=1na[i]x[i] (x[1n]N+)

思路

类似于跳楼机的做法

但是要算出 1r1l1 的答案,然后两个相减即为所求

#include<bits/stdc++.h>
using namespace std;

#define pb push_back
#define mp make_pair
#define pii pair <int,int>
#define int long long

const int N=5e5+5;
const int inf=2e18;

inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}

int n,m,l,r,mn=inf;
int d[N],a[N];
bool vis[N];
vector <pii> G[N];

inline void add(int a,int b,int c){
	G[a].pb(mp(b,c));
}

inline void SPFA(){
	queue <int> q;
	for(int i=0;i<N;++i) d[i]=inf;
	d[0]=0,vis[0]=1;
	q.push(0);
	while(!q.empty()){
		int u=q.front();q.pop();
		vis[u]=0;
		for(auto y:G[u]){
			int v=y.first,val=y.second;
			if(d[v]>d[u]+val){
				d[v]=d[u]+val;
				if(!vis[v]){
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
}

inline int query(int h){
	int ans=0;
	for(int i=0;i<mn;++i) if(h>=d[i]) ans+=(h-d[i])/mn+1;
	return ans;
}

signed main(){
	n=read(),l=read(),r=read();
	for(int i=1;i<=n;++i){
		int x=read();
		if(x){
			a[++m]=x;
			mn=min(mn,x);
		}
	}
	for(int i=0;i<mn;++i)
		for(int j=1;j<=m;++j)
			if(a[j]!=mn)
				add(i,(i+a[j])%mn,a[j]);
	SPFA();
	cout<<query(r)-query(l-1)<<endl;
}

作者:Into_qwq

出处:https://www.cnblogs.com/into-qwq/p/16451928.html

版权:本作品采用「qwq」许可协议进行许可。

posted @   Into_qwq  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-07-06 浅谈树状数组
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示