题目: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. oracle关闭

    Alert log 要每天查看 abort 关闭冷备会无法使用

  2. MAC 打开Chrome打开开发者工具的快捷键

    mac下safari和chrome打开开发者工具的快捷键相同,都是 option(alt)+command+i 这个是我的默认配置,没有更改过的.

  3. Linux 中设置 MySQL 字符集为 UTF-8

    (1)查看 MySQL 字符集 登录 mysql:mysql -u root -p 查询 mysql 字符集:mysql> show variables like 'chara%'; 说明:将 ...

  4. CCF201709-1 打酱油 java(100分)

    试题编号: 201709-1 试题名称: 打酱油 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 小明带着N元钱去买酱油.酱油10块钱一瓶,商家进行促销,每买3瓶送1瓶,或者每 ...

  5. 洛谷 3833 SHOI 2012 魔法树

    [题解] 树链剖分模板题.. #include<cstdio> #include<algorithm> #include<queue> #define N 5000 ...

  6. Python网络编程—socket(二)

    http://www.cnblogs.com/phennry/p/5645369.html 接着上篇博客我们继续介绍socket网络编程,今天主要介绍的内容:IO多路复用.多线程.补充知识点. 一.I ...

  7. Navigator的学习

      Navigator 对象包含有关浏览器的信息.注释:没有应用于 navigator 对象的公开标准,不过所有浏览器都支持该对象.   我感觉需要看什么属性和方法,直接输出这个navigator,然 ...

  8. 【Codeforces 356A】Knight Tournament

    [链接] 我是链接,点我呀:) [题意] n个人矩形m场比赛 每场比赛由编号为li~ri且之前没有被淘汰的人进行. 已知第i场的winner是xi winner会把这一场其他所有的人都淘汰. 问你n个 ...

  9. Stones HDU 1896

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1896 题目大意: 有n个石头,每个石头有:p  它所在的位置 ,d  它能扔多远 从0 开始,遇到第奇 ...

  10. $inject的用法

    controller后面的$inject是用来注入函数的变量名称的