传送门:

http://acm.hdu.edu.cn/showproblem.php?pid=1226

超级密码

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4901    Accepted Submission(s): 1591

Problem Description
Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:
密码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.

注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.

 
Input
输入数据的第一行是一个整数T(1<=T<=300),表示测试数据的数量.每组测试数据的第一行是两个整数N(0<=N<=5000)和C(2<=C<=16),其中N表示的是题目描述中的给定十进制整数,C是密码的进制数.测试数据的第二行是一个整数M(1<=M<=16),它表示构成密码的数字的数量,然后是M个数字用来表示构成密码的数字.两个测试数据之间会有一个空行隔开.

注意:在给出的M个数字中,如果存在超过10的数,我们约定用A来表示10,B来表示11,C来表示12,D来表示13,E来表示14,F来表示15.我保证输入数据都是合法的.

 
Output
对于每组测试数据,如果存在要求的密码,则输出该密码,如果密码不存在,则输出"give me the bomb please".

注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为0(除非密码本身就是0).

 
Sample Input
3
22 10
3
7 0 1

2 10
1
1

25 16
3
A B C

 
Sample Output
110
give me the bomb please
CCB

Hint

Hint

Huge input, scanf is recommended.

 
Author
Ignatius.L
 
Source
 
Recommend
Ignatius.L   |   We have carefully selected several similar problems for you:  1043 1044 1072 1067 1195 
 
题目意思:
给出n,c,m,密码必须是n这个十进制数的整数倍,c代表这个密码是C进制数,m代表这个密码只有m种字符构成,而且密码不能长于500
 
自己没有想出来,看了网上大牛的思想才懂:

不要试图去枚举十进制n的倍数来然后看看给的几个数字能否凑出来,可以想象2要翻倍多少次才能达到500位的长度,

因此要从给定的数字入手,枚举数字的各种组合情况,判断是不是n的整数倍。

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<memory.h>
using namespace std;
int n,c,m,book[],vis[];
int flag=;
struct node
{
int s[],len;
};
queue<node> q;
int mod(node t)
{
int temp=;
for(int i=;i<t.len;i++)
{
temp=(temp*c+t.s[i])%n;
}
return temp;
}
void pr(node a)
{
for(int i=;i<a.len;i++)
{
if(a.s[i]<=)
printf("%d",a.s[i]);
else
printf("%c",a.s[i]+'A'-);
}
printf("\n");
return ;
}
void bfs()
{
node t;
t.len=;
int v;
for(int i=;i<;i++)//先出来第一个结点,因为密码第一位不能为0
{
if(book[i]==)
{
t.s[]=i;
t.len=;
v=mod(t);
if(v==)
{
pr(t);
flag=;
return ;
}else
{
if(vis[v]==)
{
vis[v]=;
q.push(t);
}
}
}
}
while(!q.empty())
{
t=q.front();
q.pop();
for(int i=;i<;i++)
{
if(book[i]==)
{
t.s[t.len]=i;
t.len++;
v=mod(t);
if(v==)
{
pr(t);
flag=;
return ;
}else
{
if(vis[v]==&&t.len<)//需要判断一下数位
{
vis[v]=;
q.push(t);
}
}
t.len--;
}
}
}
return ;
}
int main()
{
int T;
char s[];
cin>>T;
while(T--)
{
flag=;
memset(vis,,sizeof(vis));
memset(book,,sizeof(book));
while(!q.empty())
{
q.pop();
}
cin>>n>>c>>m;
getchar();
for(int i=;i<m;i++)
{
cin>>s;
if(s[]<=''&&s[]>='')
{
book[s[]-'']=;
}else
{
book[+s[]-'A']=;
}
}
if(n!=)
{
bfs();
if(flag==)
cout<<"give me the bomb please"<<endl;
}else//n==0的话,不能取模,因此不能入队,特判一下
{
if(book[])
cout<<""<<endl;
else
cout<<"give me the bomb please"<<endl;
}
}
}

而且这样的话还有一个强剪枝就是如果余数相同就没必要再次入队了,

因为无论是大数还是小数如果模n同余那么再添上其他数字的话再模n还是同余的,

这样每个余数最多在队列里出现一次,也就是说队列中最多出现5000个结点,大大优化了时间。

还有要注意的一点是n=0时的特判。

code:

HDU 1226 超级密码(数学 bfs)的更多相关文章

  1. hdu 1226 超级密码(bfs+余数判重)

    题意:略过 分析:用m个数字组成一个能够被n整除的c进制数的最小值,实际上本题的关键就在于这个最小值上.  首先确定我们的思路是从小到大寻找.先查看一位数,即查看着m个数字是否能被n整除:若不能,就查 ...

  2. hdu.1226.超级密码(bfs)

    超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  3. hdu 1226 超级密码

    超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem D ...

  4. HDU 1226 超级密码(BFS) (还需研究)

    Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Desc ...

  5. HDU 1226 超级密码 (搜素)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1226 题意简单,本来是一道很简单的搜素题目. 但是有两个bug: 1.M个整数可能有重复的. 2.N可 ...

  6. HDOJ 1226 超级密码

    超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  7. 超级密码 hdu1226 bfs

    超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. HDOJ 1226 超级密码(bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1226 思路分析:题目要求寻找一串长度不大于500的C进制的密码,且该密码需要为十进制数N的整数倍. & ...

  9. HDU-1226 超级密码 (BFS+剪枝)

    Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:密 码是一个C进 ...

随机推荐

  1. 关于重定向printf出错 Error[Pe020]: identifier "FILE" is undefined 解决方案

    IAR或者Keil用到重定向printf函数出现的错误解决方案 转发请注明出处,谢谢 原创:李剀 https://www.cnblogs.com/kevin-nancy/articles/105851 ...

  2. 在ZYNQ-7000平台上利用PS点亮PL上的LED灯

    在ZYNQ-7000平台上利用PS点亮PL上的LED灯 1.实验方案 图1    实验方案系统框图 2.具体步骤 2.1.vivado工程建立 ①打开vivado集成开发环境,点击“Create Pr ...

  3. log4j整理

    <meta http-equiv="refresh" content="1"/> # log4j日志组件 #- SLF4J,一个**通用日志接口** ...

  4. php获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法

    php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...

  5. winfrom 树勾选

    树勾选 /// <summary> /// 树勾选 /// </summary> /// <param name="sender"></p ...

  6. c#-FrameWork02泛型

    泛型 l  泛型(generic)编程是一种编程范式,它利用”参数化类型”将类型抽象化,从而可以实现更为灵活的复用.把数据类型参数化 sh泛型集合 泛型集合与集合的对比 泛型集合类 非泛型集合类 Li ...

  7. oracle OTT 学习

    1.OTT概念 OTT 是 Object Type Translator 的缩写,对象类型转换器.它是用来将数据库中定义的类型(UDT)转换为C结构体类型的工具.借助OTT 可以用C语言调用OCI来访 ...

  8. spynner解析中文页面,应该显示中文字符的地方都是?的解决方案

    这个是底层的QtWebKit相关库里 用的是Qt的QString spynner在将QString转为Python的通用字符串时,没有考虑到中文编码这一块的问题. Python27\Lib\site- ...

  9. ubuntu 14.04 64bit 安装 oracle 11g r2

    参考文章:http://tutorialforlinux.com/2016/03/09/how-to-install-oracle-11g-r2-database-on-ubuntu-14-04-tr ...

  10. PHP性能检测与优化—XHProf 数据阅读

    PHP性能检测与优化—XHProf 数据阅读 一.      效果如下 请求总揽 函数调用情况 二.      参数含义 Inclusive Time              包括子函数所有执行时间 ...