密码宝盒

密码宝盒

时间限制: 2000 ms  |  内存限制: 65535 KB
难度: 3
描述

小M得到了一个宝盒,可惜打开这个宝盒需要一组神奇的密码,然而在宝盒的下面

有关于密码的提示信息:密码是一个C进制的数,并且只能由给定的M个数字中的某些构成,密码不超过500位,同时密码是一个给定十进制整数N的正整数倍,

如果这样的密码存在,那么你就可以打开宝盒并得到宝贝,如果不存在

这样的密码......那你就只能收藏这个宝盒了.

输入
输入一个T,表示有T组测试数据,(T≤500)
接下来输入N,C,M(N,C,M如上所述)( 0≤N≤5000, 1≤M≤16 , 2≤C≤16 )
然后M个数,表示密码中含有哪些数字。(输入保证合法)
用A来表示10, B来表示11, C来表示12 , D来表示13, E来表示14, F来表示15
输出
输出:密码如果存在,输入最小的那个为密码,不存在”So Sorry.”(密码不含前导零)
样例输入
3
22 10 3
7 0 1
2 10 11
25 16 3
A B C
样例输出
110
So Sorry.

CCB

//借鉴大神思路, 模拟除法算数运算可知若出现相同余数则出现循环,固可用余数标记搜索状态
#include <stdio.h>
#include <queue>
#include <string.h>
#include <algorithm>

using namespace std;

int mark[5001], item[17], pre[5001], ansAt[5001], n, m, c; //mark标记,pre为找答案记录路径,ansAt:res为i时所取得item
char ans[5001];        //记录答案

char itoc(int i)        //int -> char
{
    return i < 10 ? (i+'0') : (i-10+'A');
}

int ctoi(char c)        //char -> int
{
    return c >= '0' && c <= '9' ? (c-'0') : (c-'A'+10);
}

int bfs()
{
    queue<int> q;
    int res, temp, i;
    q.push(0);              //0压栈只为开始,无其他意义
    while(!q.empty())
    {
        temp = q.front();
        q.pop();
        for(i = 0; i < m; i++)
        {
            res = (temp*c + item[i]) % n;   //余数相同即为重复搜索
            if(!mark[res] && !(!temp && !item[i]))  //注意此处temp和item同时为0时不能用余数判断
            {
                mark[res] = 1;
                ansAt[res] = item[i];
                pre[res] = temp;
                if(res == 0)   //若余数为0则可整除,找到答案
                {
                    return 1;
                }
                q.push(res);
            }
        }
    }
    return 0;
}

int check()
{
    int temp = pre[0], i = 0;
    ans[i++] = itoc(ansAt[0]);
    while(temp)   //根据pre和ansAt构造结果
    {
        ans[i++] = itoc(ansAt[temp]);
        temp = pre[temp];
    }
    ans[i] = 0;
    if(i <= 500)   //正确结果不大于500位
    {
        return 1;
    }
    return 0;
}

int main()
{
    int t, i, len;
    char str[3];
    scanf("%d", &t);
    while(t--)
    {
        memset(mark, 0, sizeof(mark));
        memset(pre, 0, sizeof(pre));
        scanf("%d%d%d", &n, &c, &m);
        for(i = 0; i < m; i++)
        {
            scanf("%s", str);
            item[i] = ctoi(str[0]);  //char->int
        }
        sort(item, item+m);   //排序为了从小到大搜索
        if(n == 0)
        {
            if(item[0] == 0)   //为0是要特判
            {
                printf("0\n");
            }
            else
            {
                printf("So Sorry.\n");
            }
            continue;
        }
        if(bfs() && check())  //搜到且长度合法
        {
            len = strlen(ans);
            for(i = len-1; i >= 0; i--)
            {
                printf("%c", ans[i]);
            }
            printf("\n");
        }
        else               //否则
        {
            printf("So Sorry.\n");
        }
    }
    return 0;
}


以下是密码宝盒问题算法的基本流程图: 1. 输入密码宝盒的尺寸和每个格子上的数字 2. 对每一行和每一列进行求和,得到行和列的和数组 3. 遍历所有的格子,每次将当前格子的数字减去行和列的和,再将结果加上所有行和列的和的差值 4. 如果所有格子的数字都变成了 0,那么密码宝盒就是完美的;否则,密码宝盒不完美,输出提示信息 下面是基本流程图: ``` 输入密码宝盒的尺寸和每个格子上的数字 ┌─────────────┐ │ │ │ 获取输入 │ │ │ └─────────────┘ │ ▼ 对每一行和每一列进行求和,得到行和列的和数组 ┌─────────────┐ │ │ │ 求和处理 │ │ │ └─────────────┘ │ ▼ 遍历所有的格子,每次将当前格子的数字减去行和列的和,再将结果加上所有行和列的和的差值 ┌─────────────────┐ │ │ │ 数字变换和计算 │ │ │ └─────────────────┘ │ ▼ 如果所有格子的数字都变成了 0,那么密码宝盒就是完美的;否则,密码宝盒不完美,输出提示信息 ┌─────────────────────┐ │ │ │ 判断是否为完美密码宝盒 │ │ │ └─────────────────────┘ │ ▼ 输出结果 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值