hdu 1104/poj 2426 Remainder
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 #define MOD(x,y) ((x)%(y)+(y))%(y) 5 using namespace std; 6 7 bool hash[1000][2]; 8 struct node 9 { 10 int dist,modk,modm; 11 char opt; 12 }father[1000][2]; 13 int n,k,m,m_k,n_m; 14 15 void print(node cur,int cnt) 16 { 17 if( 1==cnt ) 18 { 19 putchar(cur.opt); 20 return; 21 } 22 print(father[cur.modk][cur.modm],cnt-1); 23 putchar(cur.opt); 24 } 25 26 void bfs(void) 27 { 28 queue<node> Q; 29 node sn; 30 31 m_k=MOD(m,k); 32 n_m=MOD(n,m); 33 memset(hash,false,sizeof(hash)); 34 sn.modk=MOD(n,k); 35 sn.modm=0!=n_m; 36 hash[sn.modk][sn.modm]=true; 37 sn.dist=0; 38 Q.push(sn); 39 while( !Q.empty() ) 40 { 41 node cur=Q.front(); 42 43 Q.pop(); 44 for(int i=0;i<4;i++) 45 { 46 node next; 47 48 switch( i ) 49 { 50 case 0:next.modk=MOD(cur.modk+m_k,k);next.opt='+';break; 51 case 1:next.modk=MOD(cur.modk-m_k,k);next.opt='-';break; 52 case 2:next.modk=MOD(cur.modk*m_k,k);next.modm=0;next.opt='*';break; 53 case 3:next.modk=MOD(cur.modm?n_m:0,k);next.opt='%';break; 54 default:break; 55 } 56 if( next.opt!='*' ) next.modm=cur.modm; 57 next.dist=cur.dist+1; 58 if( next.modk==MOD(n+1,k) ) {father[next.modk][next.modm]=cur;printf("%d\n",next.dist);print(next,next.dist);puts("");return;} 59 if( hash[next.modk][next.modm] ) continue; 60 hash[next.modk][next.modm]=true; 61 father[next.modk][next.modm]=cur; 62 Q.push(next); 63 } 64 } 65 puts("0"); 66 return; 67 } 68 69 int main() 70 { 71 while( scanf("%d%d%d",&n,&k,&m),n||k||m ) 72 bfs(); 73 return 0; 74 } 75 /* 76 从晚上六点开始做,到九点才得到第一个AC 77 78 【要做一会儿的bfs】 79 80 一开始努力找状态,想到了[%k][%m]的状态来判重 81 记录father节点困扰了我好一会儿,基本功啊~~(根据状态记录节点) 82 后来陆陆续续找到两个错误(多谢了poj里的discuss版) 83 1. 在hash判重之前,先修改了father的值,导致错解覆盖了正解的数据 84 2.一开始记录当前的n,还改成了long long,经过测试发现,还是溢出了 85 86 想法的改进: 87 1.状态只是 %k & %m,n的记录也是为了计算 %k & %m,但利用父节点的%k & %m就可以计算子节点的%k & %m,避免了溢出问题 88 具体地, 89 m_k = m % k; 90 n_m = n % m; 91 next.modk = ( cur.ret + m ) % k = ( cur.modk + m_k ) % k; 92 next.modk = ( cur.ret - m ) % k = ( cur.modk - m_k ) % k; 93 next.modk = ( cur.ret * m ) % k = ( cur.modk * m_k ) % k; 94 next.modk = ( cur.ret % m ) % k = cur.modm % k; //这里是变化 95 对于 +、-、%,next.modm = cur.modm; 96 而对于 * next.modm = ( cur.ret * m ) % m =0; 97 进而发现,modm只有两个值 n_m 或 0;(如果n_m!=0的话) 98 这个时候,状态也跟着改进了 [%k][2] 99 时空都得到了改进(时间的改进在于:1.初始化改进了2.用m_k记录了取余结果,计算方便了) 100 101 刷了两次,也刷了个0ms O(∩_∩)O哈! (平常是15ms) 102 */