同余最短路
同余最短路#
题型#
- 给定 个整数,求这 个整数能拼凑出多少的其他整数( 个整数可以重复取)
- 给定 个整数,求这 个整数不能拼凑出的最小(最大)的整数
- 至少要拼几次才能拼出模 余 的数
例题#
P3403 跳楼机#
题意:
给定 ,问对于 有多少个 能满足
思路:
令 表示仅通过操作 能达到的 的最小楼层
那么可得
最短路的求法是:
类比一下,让 和 变成点, 变成边权,通过跑最短路求得
因为 操作可以每次让楼层加 ,所以最后的答案就是
要 因为算当前楼
注意尽量选较小的 当作模数,可以省时空复杂度
#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 墨墨的等式#
题意:
给定 ,问对于 有多少个 能满足
思路:
类似于跳楼机的做法
但是要算出 和 的答案,然后两个相减即为所求
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2020-07-06 浅谈树状数组