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 */