题目:http://poj.org/problem?id=3539

题目大意是给定 a, b, c,求 1~h 内有多少个数可以被 a, b, c 通过加减法组成;

这是今天刚讲的神奇的——同余类 bfs 问题!

大概就是选定一个模数,就选最小的(常数可能会比较小?),不妨令作 a,构建一系列点,组成 mod a 剩余系;

然后我们要找到每个点的最小可达数,然后它加上若干个 a 就都是可达的;

对于一个点 x,它可以转移到 (x + b) % b,代价是 b ;c 同理;

从起点开始 bfs,对于本题来说就是1%a,且 dis[1%a] = 1(层数),求出 dis[] 数组,就是每个点的最小可达数;

计算答案就是对于每个余数(点),看看在1~h 中有多少个它加若干 a 可达的数,也就是 (h - dis[x]) / a + 1;

不过其实不 bfs 也可以,反正就是求最短路;

注意 dis 是 long long 哟~

代码如下:

dijkstra:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
int const maxn=1e5+;
ll h,ans,dis[maxn];
int a,b,c,hd[maxn],ct;
priority_queue<pair<ll,int> >q;
bool vis[maxn];
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
void dijkstra()
{
memset(dis,0x3f,sizeof dis);
dis[%a]=; q.push(make_pair(-,%a));
while(q.size())
{
int x=q.top().second; q.pop();
if(vis[x])continue;
vis[x]=;
for(int i=hd[x];i;i=ed[i].nxt)
{
int u=ed[i].to;
if(dis[u]>dis[x]+ed[i].w)
{
dis[u]=dis[x]+ed[i].w;
q.push(make_pair(-dis[u],u));
}
}
}
}
int main()
{
scanf("%lld%d%d%d",&h,&a,&b,&c);
if(a>b)swap(a,b); if(a>c)swap(a,c);
for(int i=;i<a;i++)
{
add(i,(i+b)%a,b);
add(i,(i+c)%a,c);
}
dijkstra();
for(int i=;i<a;i++)
{
if(dis[i]>h)continue;//!
ans+=(ll)(h-dis[i])/a+;
}
printf("%lld\n",ans);
return ;
}

dijkstra

spfa:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
int const maxn=1e5+;
ll h,ans,dis[maxn];
int a,b,c,hd[maxn],ct;
queue<int>q;
bool vis[maxn];
struct N{
int to,nxt,w;
N(int t=,int n=,int w=):to(t),nxt(n),w(w) {}
}ed[maxn<<];
void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
void spfa()
{
memset(dis,0x3f,sizeof dis);
dis[%a]=; q.push(%a); vis[%a]=;
while(q.size())
{
int x=q.front(); q.pop(); vis[x]=;
for(int i=hd[x];i;i=ed[i].nxt)
{
int u=ed[i].to;
if(dis[u]>dis[x]+ed[i].w)
{
dis[u]=dis[x]+ed[i].w;
if(!vis[u])vis[u]=,q.push(u);
}
}
}
}
int main()
{
scanf("%lld%d%d%d",&h,&a,&b,&c);
if(a>b)swap(a,b); if(a>c)swap(a,c);
for(int i=;i<a;i++)
{
add(i,(i+b)%a,b);
add(i,(i+c)%a,c);
}
spfa();
for(int i=;i<a;i++)
{
if(dis[i]>h)continue;//!
ans+=(ll)(h-dis[i])/a+;
}
printf("%lld\n",ans);
return ;
}

spfa

bfs:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
int const maxn=1e5+;
ll h,ans;
ll a,b,c,dis[maxn];//ll
queue<int>q;
bool vis[maxn];
void bfs()
{
memset(dis,0x3f,sizeof dis);
dis[%a]=; q.push(%a); vis[%a]=;
while(q.size())
{
int x=q.front(),u; q.pop(); vis[x]=;
if(dis[u=(x+b)%a]>dis[x]+b)
{
dis[u]=dis[x]+b;
if(!vis[u])/*vis[u]=1,*/q.push(u);
}
if(dis[u=(x+c)%a]>dis[x]+c)
{
dis[u]=dis[x]+c;
if(!vis[u])/*vis[u]=1,*/q.push(u);
}
}
}
int main()
{
scanf("%lld%lld%lld%lld",&h,&a,&b,&c);
if(a>b)swap(a,b); if(a>c)swap(a,c);
bfs();
for(int i=;i<a;i++)
{
if(dis[i]>h)continue;//!
ans+=(h-dis[i])/a+;
}
printf("%lld\n",ans);
return ;
}

poj3539 Elevator——同余类bfs的更多相关文章

  1. [poj 3539] Elevator (同余类bfs)

    Description Edward works as an engineer for Non-trivial Elevators: Engineering, Research and Constru ...

  2. poj 3539 Elevator——同余类bfs

    题目:http://poj.org/problem?id=3539 考虑把层数分为模a剩余系.同类内可通过+若干个a走到. 不同类之间需要通过+b.+c来走到. 需要求出每一类中最小的能走到的.即最短 ...

  3. 同余类BFS的一些瞎吹

    同余类BFS的题,是个OIer基本上都会见过一些,最好的例子就是NOIP 2018 day1  T2---货币系统 虽然这题其实是什么背包就能解决的题目,但数据一变大,出题人坏一点,就没了.... 同 ...

  4. POJ 3539 Elevator(同余类BFS)

    题意 有一部电梯,最初停在1层. 电梯有4个按键,上升a,b,c层,回到一层. 求从一层出发.能到达1~h的哪些楼层. (h<=1018,a,b,c<=105) 题解 这种h能大的图论,一 ...

  5. BZOJ2118: 墨墨的等式(同余类BFS)(数学转为图论题)

    2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2944  Solved: 1206[Submit][Status][Discu ...

  6. POJ3539 Elevator

    Time Limit: 4000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Description Edward wor ...

  7. Luogu4156 WC2016 论战捆竹竿 KMP、同余类最短路、背包、单调队列

    传送门 豪华升级版同余类最短路-- 官方题解 主要写几个小trick: \(1.O(nm)\)实现同余类最短路: 设某一条边长度为\(x\),那么我们选择一个点,在同余类上不断跳\(x\),可以形成一 ...

  8. NOIP 2017 小凯的疑惑(同余类)

    题意 给出两个互质的数a,b问最大的不能被xa+yb(x,y>=0)表示的数.(a,b<=109) 题解 NOIPday1T1一道数论题,不知埋葬了多少人的梦想. 用同余类去解释. 我们依 ...

  9. BZOJ2118 墨墨的等式[同余类最短路]

    声明:关于这题的$O(mn)$尚且未深入理解,虽然之前有跟这位神仙聊过做法但并没太懂.. $O(mn\log m)$同余最短路做法: 首先不妨抽出最小的$a_i=m$,那么剩余的$a$如果可以表示出$ ...

随机推荐

  1. SQL删除重复数据(根据多个字段),pandas的nan存入数据库报错

    delete from M_FACTOR_DATA_TEST a where (a.factor_id,a.data_date,a.stock_code) in (select factor_id,d ...

  2. js 动态加载select触发事件

    动态加载select后,手动调用一下 subjectChange函数,模拟触发change事件 function hallidChange(value) { $.ajax({ type: " ...

  3. ArrayList经典Demo

    import java.util.ArrayList; import java.util.Iterator; public class ArrayListDemo { public static vo ...

  4. Python学习笔记(3)动态类型

    is运算符 ==是值相等而is必须是相同的引用才可以 l=[1,2,3] m=[1,2,3] print(l==m) # True print(l is m) # False sys模块 getref ...

  5. Random和ArrayList的应用

    /*Random类应用与Math类应用,创建一个类, * 1)分别用Random类和Math.random()方法生成随机数. * 2) 把Math.random()方法生成的随机数,转换成1-100 ...

  6. Mac安装virtualwrapper时报错No module named virtualenvwrapper

    1. 前言 我在使用mac安装virtualwrapper的时候遇到了问题,搞了好长时间,才弄好,在这里总结一下分享出来,供遇到相同的问题的朋友使用,少走些弯路. 2. 问题说明 Mac默认系统的py ...

  7. stall and flow separation on airfoil or blade

    stall stall and flow separation Table of Contents 1. Stall and flow separation 1.1. Separation of Bo ...

  8. 洛谷 1569 [USACO11FEB]属牛的抗议

    [题解] 非常显然的DP,f[i]表示到第i个位置最多分成几组,f[i]=Max(f[i],f[j]+1) (j<i,sum[j]<=sum[i]) #include<cstdio& ...

  9. dp专题备忘录

    hdu 1024:基础dp题 hdu 1029:主元素问题,很快的解法,计数器 hdu 1069:LIS hdu 1074:数位dp,数位dp基础 hdu 1257:简单LIS,要仔细分析为什么是求最 ...

  10. Eclipse中使用JRebel实现项目热部署(Maven插件版)

    JRebel实现项目热部署(Maven插件版) 热部署,就是在应用运行过程中不进行重启,可直接进行软件升级. 在开发过程中,热部署就是在项目运行过程中变更代码,无需重启服务器即可使代码生效. tomc ...