这道题目要在解决问题之前先预处理出一个四位数的质数表,由于范围很小,只需要枚举1000~9999并用O(√n)的质数判断函数进行验证即可,当然,用线性筛或除余法也是可以的(此题时间充裕,不建议用MR素数判断)。
然后便是一个BFS,对于当前数字,只要枚举每一个它能变成的质数,判断是否已操作过,若未操作过则将其加入队列即可。
代码如下:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cmath> #include<queue> #define max(x,y) (x>y?x:y) #define min(x,y) (x<y?x:y) #define LL long long using namespace std; int n,m; bool vis[10000],Prime[10000]; struct BFS { int v,step;//v存储数字,step存储步数 }; queue<BFS> q,q_; int read() { int x=0,f=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') f=-1,ch=getchar(); while(ch>='0'&&ch<='9') (x*=10)+=ch-'0',ch=getchar(); return x*=f; } void write(int x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } bool Is_prime(int x) {for(int i=2;i*i<=x;i++) if(!(x%i)) return false;return true;}//O(√n)的质数判断函数 void Find_prime() {for(int i=1000;i<10000;i++) Prime[i]=Is_prime(i);}//枚举每一个四位数 void bfs()//BFS { if(q.empty()) return;//若队列空了则退出函数(理论上来说是不会出现这种情况的) if(q.front().v==m) {write(q.front().step),putchar('\n');return;}//达成目标就输出步数(记得换行) for(int t=1;t<=1000;t*=10) for(int i=0;i<=9;i++) {int nx=q.front().v-(q.front().v/t)%10*t+i*t;if(!vis[nx]&&Prime[nx]) vis[nx]=true,q.push({nx,q.front().step+1});}//枚举当前数字能变成的每一个质数 q.pop(),bfs();//将当前状态从队列中取出,BFS下一个状态 } int main() { memset(Prime,false,sizeof(Prime)); Find_prime();//预处理出四位数的质数表 int T=read(); while(T--) { n=read(),m=read(); memset(vis,false,sizeof(vis)); q=q_,q.push({n,0}),vis[n]=true;//记得在新的一次BFS前清空队列 bfs(); } return 0; }
版权声明:转载请注明地址