NYOJ 929 密码宝盒 || HDU 1226 超级密码

题目链接~~>

做题感悟:

              开始听了学长讲课后在杭电上做过这个题,之后又在比赛时遇见,当时有点不淡定 RE 了三次,开始以为数组开小了后来才发现没有考虑到 n = 0 ;的情况,以后即使遇到原题也应该认真读题。

题意:

         给你一个 n ,m个C进制的数。让你组合成最小的数字是 n 的倍数。

解题思路:

               这需要数学知识,r = k ( mod n ) 则 ( k * p + a ) ( mod c ) = ( r * p + a ) ( mod  n ) ;余数出现过如果再次出现就不用再次使用。

代码(本人):

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std ;
int n,m,c ;
int g[20] ;
bool vis[10000] ;
struct zhang
{
    int x,y[505],num,bu ;
} ;
bool bfs()
{
    int i,j ;
    queue<zhang>q ;
    zhang cur,next ;
    memset(vis,false,sizeof(vis)) ;
    cur.x=0 ;
    cur.num=0 ;
    cur.bu=0 ;
    q.push(cur) ;
    while(!q.empty())
    {
         cur=q.front() ;
         q.pop() ;
         for(i=0 ;i<n ;i++)
         {
             next.x=cur.x*c+g[i] ;
             if(!next.x) continue ; // 前缀不能是 0 
             next.bu=cur.bu+1 ;
             next.num=cur.num+1 ;
             next.x=next.x%m ;
             if(vis[next.x]||next.num>500) continue ; // 如果余数出现过或长度大于 500 不继续下去
             vis[next.x]=1 ;
             for(j=0 ;j<cur.num ;j++)
                next.y[j]=cur.y[j] ;
                next.y[cur.num]=g[i] ;
             if(!next.x) // 找到解输出
             {
                 for(j=0 ;j<next.num ;j++)
                  if(next.y[j]>9)
                              printf("%c",next.y[j]+55) ;
                  else        printf("%d",next.y[j]) ;
                              printf("\n") ;
                  return true ;
             }
             q.push(next) ;
         }
    }
    return false ;
}
int main()
{
    int T,i ;
    char ch ;
    scanf("%d",&T) ;
    while(T--)
    {
        scanf("%d%d%d",&m,&c,&n) ;
        for(i=0 ;i<n ;i++)
        {
            getchar() ;
            scanf("%c",&ch) ;
            if(ch>='A'&&ch<='F')
                    g[i]=ch-55 ;
            else    g[i]=ch-'0' ;
        }
        sort(g,g+n) ; // 排序让第一个找到的是最小的
        if(!m) // 0 需要特判一下
        {
            if(!g[0])
                    printf("0\n") ;
            else
                    printf("give me the bomb please\n") ;
            continue ;
        }
        if(!bfs())
            printf("give me the bomb please\n") ;
    }
    return 0 ;
}

代码:

 
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#include<iostream>
#define MX 50005
using namespace std ;
int n,c,m ;
int g[18] ;
bool vis[MX] ;
struct zhang
{
    int x,m,pre,cnt ;
}q[MX] ;
void gettep(int k)
{
    if(k==-1)
         return ;
    gettep(q[k].pre) ;
    if(q[k].x>=10)
            printf("%c",q[k].x+55) ;
    else    printf("%c",q[k].x+'0') ;
    return ;
}
int bfs()
{
    int head=0,tail=-1 ;
    memset(vis,false,sizeof(vis)) ;
    for(int i=0 ;i<m ;i++)
    {
        if(!g[i]) continue ;
        zhang next ;
        next.pre=-1 ;
        next.x=g[i] ;
        next.m=g[i]%n ;
        vis[next.m]=true ;
        next.cnt=1 ;
        q[++tail]=next ;
    }
    while(head<=tail)
    {
        int h=head ;head++ ;
        if(q[h].cnt>500) continue  ;
        if(!q[h].m)
        {
            gettep(h) ;
            return true  ;
        }
        for(int i=0 ;i<m ;i++)
        {
            int key=(q[h].m*c+g[i])%n ;
            if(vis[key]) continue ;
            vis[key]=true ;
            zhang tep ;
            tep.m=key ;   tep.x=g[i] ;
            tep.pre=h ;   tep.cnt=q[h].cnt+1 ;
            q[++tail]=tep ;
        }
    }
    return false ;
}
int main()
{
    int T,i ;
    char ch ;
    scanf("%d",&T) ;
    while(T--)
    {
        scanf("%d%d%d",&n,&c,&m) ;
        for(i=0 ;i<m ;i++)
        {
            cin>>ch ;
            if(ch>='A'&&ch<='F')
                   g[i]=ch-55 ;
            else   g[i]=ch-'0' ;
        }
        sort(g,g+m) ;
        if(!n)
        {
            if(!g[0]) printf("0") ;
            else      printf("So Sorry.") ;
                      puts("") ;
            continue ;
        }
        if(!bfs())
            printf("So Sorry.") ;
            puts("") ;
    }
    return 0 ;
}
        

优代码:

#include <queue>
#include <string>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 5005;
bool vis[N];
string ans;
int a[17],pre[N],ansAt[N],n,m,c;
int ctoi(char c)
{
    return c >= '0' && c <= '9' ? c - '0' : c - 'A' + 10;
}
char itoc(int i)
{
    return i <= 9 ? i + '0' : i + 'A' - 10;
}
bool bfs()
{
    queue<int> q;
    q.push(0);
    while(!q.empty())
    {
        int cur = q.front();q.pop();
        for(int i=0;i<m;i++)
        {
            int nxt = (cur * c + a[i]) % n;
            if(cur == 0 && a[i] == 0 || vis[nxt])
                       continue;
            vis[nxt] = true;
            ansAt[nxt] = a[i];
            pre[nxt] = cur;
            if(nxt == 0)
                      return true;
            q.push(nxt);
        }
    }
    return false;
}

bool check()
{
    ans = "";
    int p = 0;
    do
    {
        ans += itoc(ansAt[p]);
        p = pre[p];
    }while(p);
    return (int)ans.size() <= 500;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,false,sizeof(vis));
        scanf("%d%d%d",&n,&c,&m);
        for(int i=0;i<m;i++)
        {
            char num[3];
            scanf("%s",num);
            a[i] = ctoi(num[0]);
        }
        sort(a,a+m);
        if(n == 0)
        {
            puts(a[0] == 0 ? "0" : "So Sorry.");
            continue;
        }
        if(bfs() && check())
        {
            for(int i=(int)ans.size()-1;i>=0;i--)
                putchar(ans[i]);
            puts("");
        }
        else
            puts("So Sorry.");
    }
	return 0;
}
        
 

你可能感兴趣的:(NYOJ 929 密码宝盒 || HDU 1226 超级密码)