【luogu3403】跳楼机 [同余最短路]
P3403 跳楼机
经过改造,srwudi的跳楼机可以采用以下四种方式移动:
向上移动x层;向上移动y层;向上移动z层;回到第一层。
一个月黑风高的大中午,DJL来到了srwudi的家,现在他在srwudi家的第一层,碰巧跳楼机也在第一层。DJL想知道,他可以乘坐跳楼机前往的楼层数。
yyb:先只考虑只用\(y,z\)两种移动方式,它们一定能够到达一些楼层,
那么这些楼层再只用\(x\)拓展就能够计算答案。
那么我们这样子计算答案,设\(dis[i]\)表示可以到达\(mod\ x=i\)楼层的最小值,
很巧妙!同余最短路
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100000+10,M=100000+10,inf=0x3f3f3f3f;
int x,y,z;
ll n,ans=0;
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<2];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
queue<int>q;bool vis[N];
ll dis[N];
void spfa(){
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push(1),vis[1]=1,dis[1]=1;
while(!q.empty()){
int u=q.front();q.pop(),vis[u]=0;
for(int i=head[u],v,w;i;i=e[i].nxt)
if(dis[v=e[i].v]>dis[u]+(w=e[i].w)){
dis[v]=dis[u]+w;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
int main(){
// freopen("in.txt","r",stdin);
rd(n),rd(x),rd(y),rd(z);
if(n==1||x==1||y==1||z==1) return printf("%lld",n),0;
for(int i=0;i<x;++i) add(i,(i+y)%x,y),add(i,(i+z)%x,z);
spfa();
for(int i=0;i<x;++i)
if(dis[i]<=n) ans+=(n-dis[i])/x+1;
printf("%lld",ans);
return 0;
}
[国家集训队]墨墨的等式
和跳楼机那题是一样的==
#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ll long long
const int N=12+10,M=500000+10,inf=0x3f3f3f3f;
int n,a[N];
ll b1,b2,ans=0;
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[M],tot=0;
struct edge{int v,w,nxt;}e[M*20];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
queue<int>q;bool vis[M];
ll dis[M];
void spfa(){
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push(0),vis[0]=1,dis[0]=0;
while(!q.empty()){
int u=q.front();q.pop(),vis[u]=0;
for(int i=head[u],v,w;i;i=e[i].nxt)
if(dis[v=e[i].v]>dis[u]+(w=e[i].w)){
dis[v]=dis[u]+w;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
int main(){
freopen("in.txt","r",stdin);
rd(n),rd(b1),rd(b2);
for(int i=1;i<=n;++i) rd(a[i]);
sort(a+1,a+n+1);
for(int i=0;i<a[1];++i)
for(int j=2;j<=n;++j) add(i,(i+a[j])%a[1],a[j]);
spfa();
for(int i=0;i<a[1];++i){
if(dis[i]<=b1-1) ans-=(b1-1-dis[i])/a[1]+1;
if(dis[i]<=b2) ans+=(b2-dis[i])/a[1]+1;
}
printf("%lld",ans);
return 0;
}