zoukankan      html  css  js  c++  java
  • hdu 1226 超级密码(bfs+余数判重)

    题意:略过

    分析:用m个数字组成一个能够被n整除的c进制数的最小值,实际上本题的关键就在于这个最小值上。

        首先确定我们的思路是从小到大寻找。先查看一位数,即查看着m个数字是否能被n整除;若不能,就查看任意可能的两位数组合...可是如此一来,预算量太大。于是我们考虑是否存在冗余量。

        已知A,B两个数(A<B),A%n==x,B%n==x,我们称其为同余,那么以它们为基础的相同变换(从一位数到两位数):A*c+C,B*c+C,这两个数同样同余,(A*c+C)%n==((A*c)%n+C%n)%n==(((A%n)*c)%n+C%n)%n==(((B%n)*c)%n+C%n)%n==(B*c+C)%n。所以,若我们能够在由 B 为基础扩展出的数字中找到一个能被 n 整除的值,那经过相同的变换,由 A 扩展出的数字一定也能被 n 整除,并且一定更小。

        根据以上推论,我们知道一旦我们发现一个余数为x的数字(因为是从小到大查找,该数字必然是最小值),那么之后凡是余数为x的数字都可以忽略不计。由于题目中给出的数字n<=5000,所以我们用bfs搜索,最多只需查找5000个状态,计算量大幅减少。

    错误:n==0,当且仅当m个数字中含有0,答案为0;否则,无解。

    注意:本题是pku 1465的延伸——由10进制数改为任意进制数,但是时限过于宽泛(也可能是数据太水了),导致用这道题的思路解题严重超时。

    这是最初的思路,把每一个扩展的数字都加入队列,运算量太大。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<queue>
      5 #include<algorithm>
      6 using namespace std;
      7 
      8 const int MAXN=5555;
      9 const int N=22;
     10 
     11 struct Node{
     12     char s[MAXN];
     13     int len;
     14 };
     15 
     16 int md[MAXN];
     17 int num[N];
     18 int n,c,m;
     19 queue<Node>q;
     20 
     21 int Num(char ch)
     22 {
     23     if(ch>='0'&&ch<='9')
     24         return ch-'0';
     25     return ch-'A'+10;
     26 }
     27 
     28 int qmod(Node e)
     29 {
     30     int cnt=0;
     31     for(int i=0;i<e.len;i++)
     32         cnt=(cnt*c+e.s[i])%n;
     33     return cnt;
     34 }
     35 
     36 void print(Node e)
     37 {
     38     for(int i=0;i<e.len;i++)
     39         if(e.s[i]>=0&&e.s[i]<=9)
     40             printf("%d",e.s[i]);
     41         else
     42             printf("%c",e.s[i]-10+'A');
     43     printf("
    ");
     44 }
     45 
     46 int bfs()
     47 {
     48     memset(md,0,sizeof(md));
     49     while(!q.empty())
     50         q.pop();
     51 
     52     Node e;
     53     for(int i=1;i<16;i++)
     54     {
     55         if(num[i]){
     56             e.s[0]=i;
     57             e.len=1;
     58             int cnt=qmod(e);
     59             if(cnt==0){
     60                 print(e);
     61                 return 1;
     62             }
     63             if(!md[cnt]){
     64                 q.push(e);
     65                 md[cnt]=1;
     66             }
     67         }
     68     }
     69     while(!q.empty())
     70     {
     71         e=q.front();q.pop();
     72         /*
     73         for(int i=0;i<e.len;i++)
     74             printf("%d",e.s[i]);
     75         printf("
    ");
     76         */
     77         for(int i=0;i<16;i++)
     78         {
     79             if(num[i]){
     80                 e.s[e.len]=i;
     81                 e.len++;
     82                 if(e.len>=500)
     83                     return -1;
     84 
     85                 int cnt=qmod(e);
     86                 if(cnt==0){
     87                     print(e);
     88                     return 1;
     89                 }
     90                 if(!md[cnt]){
     91                     q.push(e);
     92                     md[cnt]=1;
     93                 }
     94                 e.len--;
     95             }
     96         }
     97     }
     98     //printf("??
    ");
     99     return -1;
    100 }
    101 
    102 int main()
    103 {
    104     int T;
    105     scanf("%d",&T);
    106     while(T--)
    107     {
    108         scanf("%d%d%d",&n,&c,&m);
    109 
    110         memset(num,0,sizeof(num));
    111         for(int i=0;i<m;i++)
    112         {
    113             char x[2];
    114             scanf("%s",x);
    115             num[Num(x[0])]=1;
    116         }
    117         if(n==0)
    118             if(num[0])
    119                 printf("0
    ");
    120             else
    121                 printf("give me the bomb please
    ");
    122         else{
    123             int ans=bfs();
    124             if(ans==-1)
    125                 printf("give me the bomb please
    ");
    126         }
    127     }
    128     return 0;
    129 }
    View Code

    做完pku 1465 后,又回过头来做,忘记加密码长度的限制 len<=500,狠狠的wa了一发

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<queue>
      5 #include<algorithm>
      6 using namespace std;
      7 
      8 const int MAXN=5010;
      9 const int N=16;
     10 
     11 struct Node{
     12     int pre;
     13     int r;
     14     int d;
     15     int len;
     16 };
     17 
     18 int vis[MAXN];
     19 int num[N];
     20 int n,c,m;
     21 Node q[MAXN];
     22 
     23 int Num(char ch)
     24 {
     25     if('0'<=ch&&ch<='9')
     26         return ch-'0';
     27     return ch-'A'+10;
     28 }
     29 
     30 void print(int x)
     31 {
     32     if(q[x].pre==-1)
     33         return ;
     34     print(q[x].pre);
     35     if(q[x].d>=10)
     36         printf("%c",q[x].d-10+'A');
     37     else
     38         printf("%d",q[x].d);
     39 }
     40 
     41 int bfs()
     42 {
     43     memset(vis,0,sizeof(vis));
     44     int dl,dr;
     45     dl=dr=0;
     46     Node u,v;
     47     u.pre=-1;
     48     u.d=0;
     49     u.r=0;
     50     u.len=0;
     51     q[dr++]=u;
     52     vis[0]=1;
     53 
     54     int ok=0;
     55     while(dl<dr)
     56     {
     57         u=q[dl++];
     58         for(int i=0;i<m;i++)
     59         {
     60             int r=u.r*c+num[i];
     61             if(r>=n&&r%n==0){
     62                 print(dl-1);
     63                 if(num[i]>=10)
     64                     printf("%c
    ",num[i]-10+'A');
     65                 else
     66                     printf("%d
    ",num[i]);
     67                 return 1;
     68             }
     69             r=r%n;
     70             if(!vis[r]){
     71                 vis[r]=1;
     72                 v.r=r;
     73                 v.d=num[i];
     74                 v.pre=dl-1;
     75                 v.len=u.len+1;
     76                 if(v.len>500)
     77                     return -1;
     78                 q[dr++]=v;
     79             }
     80         }
     81     }
     82     return -1;
     83 }
     84 
     85 int main()
     86 {
     87     int T;
     88     scanf("%d",&T);
     89     while(T--)
     90     {
     91         scanf("%d%d%d",&n,&c,&m);
     92         memset(num,-1,sizeof(num));
     93         for(int i=0;i<m;i++)
     94         {
     95             char s[2];
     96             scanf("%s",s);
     97             num[i]=Num(s[0]);
     98         }
     99         sort(num,num+m);
    100 
    101         if(n==0)
    102             if(num[0]==0)
    103                 printf("0
    ");
    104             else
    105                 printf("give me the bomb please
    ");
    106         else{
    107             int ans=bfs();
    108             if(ans==-1)
    109                 printf("give me the bomb please
    ");
    110         }
    111     }
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    无熟人难办事?—迪米特法则
    考题抄错会做也白搭—模板方法模式
    简历复印—原型模式
    Android Studio 安装及常见问题
    雷锋依然在人间——工厂方法模式
    欢迎测试
    客户端程序设计V1
    Linux服务器端程序设计V1
    【Alpha】最后一篇
    【Alpha】开发日志Day10-0721
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3348660.html
Copyright © 2011-2022 走看看