题目: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. JavaScipt30(第六个案例)(主要知识点:给数字加千分号的正则)

    承接上文,这是第6个案例: 附上项目链接: https://github.com/wesbos/JavaScript30 这个主要是要实现在给定的json里匹配出搜索框里的city or state, ...

  2. Haoop Mapreduce 中的FileOutputFormat类

    FileOutputFormat类继承OutputFormat,需要提供所有基于文件的OutputFormat实现的公共功能,主要有以下两点: (1)实现checkOutputSpecs方法 chec ...

  3. ndk编译libpcap 1.7.4(最终解决方法)

    具体方法和测试见上一篇. 后来才知道,LIBPCAP本来就写了几套获取网卡的函数,这样就简单了.和上篇一样,把那5个文件从LINUX下托下来. 上篇忘了说了,还要将LINUX中/usr/include ...

  4. 多校1007 Naive Operations

    >>点击进入原题测试<< 思路:好像是第一次这么印象深刻的写线段树,说实话,这个题确实很有意思,值得学习. 看了大神讲解视频,但是自己写的还是超时了. 参考来自 https:/ ...

  5. ansible plugins简介

    ansible插件是增强ansible的核心功能的代码片段,ansible使用插件架构来实现丰富,灵活和可扩展的功能集. Ansible提供了许多方便的插件,您可以轻松编写自己的插件. 下边简单介绍A ...

  6. Leetcode 79.单词搜索

    单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...

  7. [K/3Cloud] 首页增加一个自定义页签及页面内容

    在K3Cloud登录后的门户首页增加一个页签,如增加一个[BBS论坛] 2013-7-30 11:18:51 上传 下载附件 (84.81 KB)  增加页签 可以这么来做: 进入BOS IDE ,找 ...

  8. 欧拉回路输出(DFS,不用回溯!)Watchcow POJ 2230

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8109   Accepted: 3551   Special Judge D ...

  9. JAVA内存模型与线程以及volatile理解

    Java内存模型是围绕在并发过程中如何处理原子性.可见性.有序性来建立的. 一.主内存与工作内存 Java内存模型主要目标是在虚拟机中将变量存储到内存和从内存中取出变量.这里的变量包括:实例字段.静态 ...

  10. MYSQL中的数值型数据类型与字符串类型

    /* 数值型数据类型主要用来存储数字,包含的类型有: TINYINT.SMALLINT.MEDIUMINT. INT(INTEGER). BIGINT TINGINT占1个字节,SMALLINT占2个 ...