传送门:

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. TOJ 2939 解救小Q

    描述 小Q被邪恶的大魔王困在了迷宫里,love8909决定去解救她.迷宫里面有一些陷阱,一旦走到陷阱里,就会被困身亡:(,迷宫里还有一些古老的传送阵,一旦走到传送阵上,会强制被传送到传送阵的另一头. ...

  2. C++ Memory System Part3 : 优化

    前面的系列我们讲了自定义new和delete操作,其中针对deleteArray的问题还有需要优化的地方.我们这次就针对POD类型进行一次优化. 下面的代码是针对POD类型的模板函数实现,分别为New ...

  3. Java学习第十八天

    1:Map(掌握) (1)将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. (2)Map和Collection的区别? A:Map 存储的是键值对形式的元素,键唯一,值可以重 ...

  4. docker-compose 安装solr+ikanalyzer

    docker-compose.yml version: '3.1' services: solr: image: solr restart: always container_name: solr p ...

  5. js【jquery】 - DOM操作

    1.修改元素样式 js方式: var div2 = document.getElementById("") div2.style.width = '200px'; div2.cla ...

  6. android JNI学习之一

    执行System.loadLibrary()函数时,VM会反向调用*.so里的JNI_OnLoad()函数.用途有二:1. VM询问此*.so使用的JNI版本编号.2. VM要求*.so做一些初期设定 ...

  7. mysql应用学习-windows(64位)安装和配置mysql(5.6.20)

    下载安装包MySQL Installer 下载地址1:http://dev.mysql.com/downloads/windows/installer/ 说明:官网当前版本 5.6.22:虽然只有32 ...

  8. JS监测鼠标指针位置

    需求1:鼠标移入正方形的时候,蓝色小圆点跟随鼠标滚动(不许蓝色小圆点超出正方形区域),正方形里实时显示当前鼠标相对于body的坐标. <!DOCTYPE html> <html la ...

  9. VS如何自动创建函数头 函数说明

    这样创建,这种方法在VS2008和VS2013下都可以. 这是效果 如何自定义格式呢? 第一步点击这个按钮 这个工具条需要安装VAssistX,如何安装这里不细说了. 第二步,点击这个按钮 第三步 点 ...

  10. 16_AOP入门准备_Jdk动态代理模式

    [工程截图] [PersonDao.java] package com.HigginCui.daoProxy; //目标类接口 public interface PersonDao { public ...