链接:点击打开链接
题意:给你N,K,M,有四个操作,一个是+M,一个是-M,一个是*M,一个是%M.什么时候可以得到初始的(N+1)%K==当前的N%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 (想清楚标记的目的是避免结果重复)]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<string>
using namespace std;
struct node{
int x;
int count;
string r;
};
int n,k,m,km;
int vis[100010];
void dfs(){
int i;
queue<node>Q;
node p,q;
p.x=n;
p.count=0;
p.r="";
vis[(n%k+k)%k]=1;
Q.push(p);
while(!Q.empty()){
p=Q.front();
Q.pop();
if(((n+1)%k+k)%k==(p.x%k+k)%k){
printf("%d\n",p.count);
cout<<p.r<<endl;
return;
}
for(i=0;i<4;i++){
q=p;
q.count=p.count+1;
if(i==0){
q.x=(p.x+m)%km;
q.r=p.r+'+';
}
else if(i==1){
q.x=(p.x-m)%km;
q.r=p.r+'-';
}
else if(i==2){
q.x=(p.x*m)%km;
q.r=p.r+'*';
}
else if(i==3){
q.x=((p.x%m+m)%m)%km;
q.r=p.r+'%';
}
if(!vis[(q.x%k+k)%k]){
Q.push(q);
vis[(q.x%k+k)%k]=1;
}
}
}
printf("0\n");
}
int main(){
while(~scanf("%d %d %d",&n,&k,&m)){
if(n==0&&k==0&&m==0)
break;
km=k*m;
memset(vis,0,sizeof(vis));
dfs();
}
return 0;
}