hdu 超級密碼 1226

/*
同餘的定義:如果m|(a-b)則a同餘b即a與b對m取餘後的餘數相同
定理:
【1】如果a1同餘b1(mod m) a2同餘b2(mod m)則a1*a2同餘b1*b2(mod m)
【2】如果a1同餘b1(mod m)  a2同餘b2(mod m)則a1+a2同餘b1+b2(mod m)
證明:
1)a1=b1+k1*m  a2=b2+k2*m
a1*a2=b1*b2+(k1*b2+k2*b1+k1*k2*m)m
所以a1*a2同餘b1*b2(mod m)
2)
a1=b1+k1*m  a2=b2+k2*m
a1+a2=b1+b2+(k1+k2)m
所以a1+a2同餘b1+b2(mod m)


如果a和b同餘則成上同一個數後一定還是同餘的
證明:假設數乘上一個數x 
a同餘b(mod m) x同餘x(mod m)
運用上述定理得ax同餘bx(mod m)
舉個例子:
N=11 C=10
10
0 1 2 3 4 5 6 7 8 9 10
123同餘2(mod m)當在後面加上一個數後相當於先乘上10 兩個數還同餘 在加上同一個數後還同餘 即餘數相同那麼就沒必要
搜123了
所以我們標記一下餘數就可以了,因爲餘數最多有5000個 
*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int num[20],N,C,flag[5005];//flag數組標記r數是否出現過如果餘數已經出現過就沒必要在進行搜索了,num的0,1判斷是否有這個數,也減少了排序
struct node
{
    int nu[505];
    int len;//數的長度
};
void Print(node q)//數的輸出
{
    int i;
    for(i=0; i<q.len; i++)
    {
        if(q.nu[i]<10)
            printf("%d",q.nu[i]);
        else
            printf("%c",q.nu[i]+'A'-10);
    }
    puts("");
}
int Mod(node q)//大數取模
{
    int i,temp=0;
    for(i=0; i<q.len; i++)
    {
        temp=(temp*C+q.nu[i])%N;
    }
    return temp;
}
int bfs()
{
    int i;
    queue<node> v;
    while(!v.empty())
        v.pop();
    node l;
    for(i=1; i<16; i++)//這一層for循環是把每個元素都放到隊列裏頭,隊列中的點的長度都爲1
    {
        if(!num[i])//當num[i]爲0時說明i這個數不存在
            continue;
        l.len=1;//把每個數的長度都初始化爲1
        l.nu[0]=i;
        int r=Mod(l);
        if(r==0)
        {
            Print(l);
            return 1;
        }
        else
        {
            flag[r]=1;
            v.push(l);
        }
    }
    //這時隊列裏頭的元素的長度都爲1
    while(!v.empty())
    {
        l=v.front();
        v.pop();
        for(i=0; i<16; i++)
        {
            if(num[i]==0)
                continue;
            l.nu[l.len]=i;
            l.len++;//這個地方自加1是在l這個點後依次加上每個數後在判斷
            if(l.len>499)
                continue;
            int r=Mod(l);
            if(r==0&&l.len<500)
            {
                Print(l);
                return 1;
            }
            else
            {
                if(flag[r]==0&&l.len<499)
                {
                    flag[r]=1;
                    v.push(l);
                }
            }
            l.len--;//這個地方減1還是保持l這個點的長度變爲原來的長度(這樣就相當於用這個點向四周擴散)
        }
    }
    return 0;
}
int main()
{
    int t,i,j,m;
    char dd;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));
        memset(flag,0,sizeof(flag));
        scanf("%d%d%d",&N,&C,&m);
        for(i=0; i<m; i++)
        {
            getchar();
            scanf("%c",&dd);
            if(dd>='A')
                num[dd-'A'+10]=1;
            else
                num[dd-='0']=1;
        }
        if(N==0)
        {
            if(num[0])
                printf("0\n");
            else
                printf("give me the bomb please\n");
            continue;
        }
        int aa=bfs();
        if(!aa)
            printf("give me the bomb please\n");
    }
    return 0;
}
發佈了64 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章