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
  • 相关阅读:
    POJ 1681 Painter's Problem(高斯消元法)
    HDU 3530 Subsequence(单调队列)
    HDU 4302 Holedox Eating(优先队列或者线段树)
    POJ 2947 Widget Factory(高斯消元法,解模线性方程组)
    HDU 3635 Dragon Balls(并查集)
    HDU 4301 Divide Chocolate(找规律,DP)
    POJ 1753 Flip Game(高斯消元)
    POJ 3185 The Water Bowls(高斯消元)
    克琳:http://liyu.eu5.org
    WinDbg使用
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3348660.html
Copyright © 2011-2022 走看看