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("\n"); 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("\n"); 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("??\n"); 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\n"); 120 else 121 printf("give me the bomb please\n"); 122 else{ 123 int ans=bfs(); 124 if(ans==-1) 125 printf("give me the bomb please\n"); 126 } 127 } 128 return 0; 129 }
做完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\n",num[i]-10+'A'); 65 else 66 printf("%d\n",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\n"); 104 else 105 printf("give me the bomb please\n"); 106 else{ 107 int ans=bfs(); 108 if(ans==-1) 109 printf("give me the bomb please\n"); 110 } 111 } 112 return 0; 113 }