题目描述(已转换成中文)
给你两个四位的素数a,b。
a可以改变某一位上的数字变成c,但只有当c也是四位的素数时才能进行这种改变。
请你计算a最少经过多少次上述变换才能变成b。
例如:1033 -> 8179
1033
1733
3733
3739
3779
8779
8179
最少变换了6次。
输入格式
第一行输入整数T,表示样例数。 (T <= 100)
每个样例输入两个四位的素数a,b。(没有前导零)
输出格式
对于每个样例,输出最少变换次数,如果无法变换成b则输出"Impossible"。
输入输出样例
输入
3
1033 8179
1373 8017
1033 1033
输出
6
7
0
题目链接
分析:
一个四位素数改变它四个位上的某一个数,变成另一个四位素数,这种操作称为:我们对原来的素数进行了一次变换。这道题就是求一个四位素数a变换成一个四位素数b所要进行的最少变换次数,要求每一次变换之后,得到新的四位数也是素数。
所以我们先要打表求出四位数中的素数(这道题我用的是埃氏筛,其实常见还是用欧拉筛,都行)。主函数内输入样例数,再分别输入每组的两个素数,输入素数之前清零vis数组(标记某个素数是否之前通过变换出现过),如果输入的a和b相同,则不进行操作,直接输出0;否则调用bfs函数。
bfs(a, b)函数内,先把原来的节点压入队列(x是素数的具体值,s是已经变换了的次数),之后分别对队首元素的个位、十位、百位、千位进行变换。用临时变量u表示变换后的四位数,check[u]是标记u是否为素数(之前通过init()函数打表得到的),之后对u进行一系列判断,若u是第一次被变换得到,并且是素数,就把新的节点m(m表示u的具体值和变换次数)压入队列,并且vis[u] = 1。直到u == b,输出从a到u的变换次数,并且直接返回,结束bfs函数;如果队列已经空了,还没找到要得到的四位素数,输出Impossible。
这道题需要注意的地方:
大家可能有这种思想:我直接把原素数四个位的数字直接替换成b四个位上的数不就好了,这样不就最多变换四次就得到了吗?其实,这道题要求我们变换过程中得到的中间数也要是素数,所以我们在依次替换a的每个位上的数的过程中,得到的中间数可能不是素数,这是不符合条件的,所以还是乖乖bfs吧,这种题不会这么沙雕的hhhh
对个位的数字进行变换的时候,个位数不用变成偶数(个位数是偶数的四位数必不是素数),这样就可以减少一些操作。并且在变换的时候,因为是通过for循环改变某个位上的数,所以还要判断每一次变换得到的数与它变换前的前一个数是否相等,不然相当于没变换。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x =