题目链接~~>
开始做这一题时很快便写出来了,但是找不到结束条件,用一个数组标记但是数有可能很大,这样会标记不了,于是乎百度了一下,要%k * m,这样会将很大的数缩小到k * m的范围内,这样就可以标记了,但是还是不明白为什么%k * m,为什么不 % k。下面是某个大牛的解释:
题意:(注意题目中的%是指mod)开始给了你n, k, m。。。。每次由+m, -m, *m, modm得到新的N,继续对N这样的操作,直到(n+1) mod k== N mod k时结束。。。并且打印路径。
%与mod的区别:%出来的数有正有负,符号取决于左操作数。。。而mod只能是正(因为a = b * q + r (q > 0 and 0 <= r < q), then we have a mod q = r 中r要大于等于0小于q)。。。。。所以要用%来计算mod的话就要用这样的公式:a mod b = (a % b + b) % b ,括号里的目的是把左操作数转成正数。由于新的N可以很大,所以我们每一步都要取%,而且最后要mod k,正常来说每步都%k就行了,但是由于其中的一个操作是N%m,所以我们每一步就不能%k了(%k%m混用会导致%出来的答案错误),而要%(k *m)(其实%(k,m的公倍数都行))然后,vis[这里放的要是遍历的点mod k (想清楚标记的目的是避免结果重复)]
而那四个操作避免过大则取余就可以了,而不需要取mod。
代码:
#include<stdio.h> #include<string.h> #include<math.h> #include<queue> using namespace std ; int n,m,k,c,mx,r1,r2,km; int vis[2222222],p[10000],father[10000]; struct zhang { int x,y,bu; }; int bfs(int x) { queue<zhang>q; zhang current,next; int i=0; memset(vis,0,sizeof(vis)); current.x=x; current.y=0; current.bu=0; q.push(current); father[0]=0; while(!q.empty()) { current=q.front(); q.pop(); if(vis[(current.x%km+km)%km]) continue; next.x=((current.x+m)%km+km)%km; next.y=++i; next.bu=current.bu+1; father[next.y]=current.y; p[next.y]=1; if(next.x%k==c) { mx=next.bu; return next.y; } else q.push(next); next.x=((current.x-m)%km+km)%km; next.y=++i; next.bu=current.bu+1; father[next.y]=current.y; p[next.y]=2; if(next.x%k==c) { mx=next.bu; return next.y; } else q.push(next); next.x=((current.x*m)%km+km)%km; next.y=++i; next.bu=current.bu+1; father[next.y]=current.y; p[next.y]=3; if(next.x%k==c) { mx=next.bu; return next.y; } else q.push(next); next.x=((current.x%m+m)%m)%km; next.y=++i; next.bu=current.bu+1; father[next.y]=current.y; p[next.y]=4; if(next.x%k==c) { mx=next.bu; return next.y; } else q.push(next); vis[(current.x%km+km)%km]=1;//标记 } return -1; } void find(int x)//递归打印路径 { if(father[x]!=x) { find(father[x]); if(p[x]==1) printf("+"); else if(p[x]==2) printf("-"); else if(p[x]==3) printf("*"); else if(p[x]==4) printf("%%"); } } int main() { int q; while(scanf("%d%d%d",&n,&k,&m)!=EOF) { if(n==0&&k==0&&m==0) break; km=k*m; c=((n+1)%k+k)%k;//题目中说r为正 q=bfs(n); if(q!=-1) { printf("%d\n",mx); find(q); } else printf("0"); printf("\n"); } return 0; }