给出一篇有关素数线性筛和区间筛的博客,有兴趣的读者可以自取。
本题大意:
给定两个四位的素数,没有前导零,每次变换其中的一位,最终使得两个素数相等,输出最小变换次数。要求变换过程中的数也都是素数。
本题思路:
求最小步数,用BFS,判断素数,用欧拉筛打表。
参考代码:

1 #include <cstdio> 2 #include <queue> 3 #include <map> 4 #include <cstring> 5 using namespace std; 6 7 8 int star, finish, ans, total = 0; 9 const int maxn = 10000 + 5; 10 bool isprime[maxn]; 11 bool isvisited[maxn]; 12 int prime[1300]; 13 14 struct node{ 15 int cur, step; 16 } now, Next; 17 18 void get_prime() {//欧拉筛打表 19 memset(isprime, false, sizeof(isprime)); 20 for(int i = 2; i < maxn; i ++) { 21 if(!isprime[i]) 22 prime[total ++] = i; 23 for(int j = 0; j < total; j ++) { 24 if(prime[j] * i > maxn) break; 25 isprime[prime[j] * i] = true; 26 if(i % prime[j] == 0) break; 27 } 28 } 29 } 30 31 int bfs() { 32 queue <node> Q; 33 isvisited[star] = true; 34 now.cur = star; 35 now.step = 0; 36 Q.push(now); 37 while(!Q.empty()) { 38 char num[5]; 39 now = Q.front(); 40 Q.pop(); 41 if(now.cur == finish) return now.step; 42 for(int i = 0; i < 4; i ++) { 43 sprintf(num, "%d", now.cur); 44 for(int j = 0; j < 10; j ++) { 45 if(j == 0 && i == 0) continue; 46 if(i == 0) 47 Next.cur = j * 1000 + (num[1] - '0') * 100 + (num[2] - '0') * 10 + (num[3] - '0'); 48 else if(i == 1) 49 Next.cur = j * 100 + (num[0] - '0') * 1000 +(num[2] - '0') * 10 + (num[3] - '0'); 50 else if(i == 2) 51 Next.cur = j * 10 + (num[0] - '0') * 1000 + (num[1] - '0') * 100 + (num[3] - '0'); 52 else if(i == 3) 53 Next.cur = j + (num[0] - '0') * 1000 + (num[1] - '0') * 100 + (num[2] - '0') * 10; 54 if(!isprime[Next.cur] && !isvisited[Next.cur]) { 55 Next.step = now.step + 1; 56 isvisited[Next.cur] = 1; 57 Q.push(Next); 58 } 59 } 60 } 61 } 62 return -1; 63 } 64 65 int main () { 66 memset(isvisited, false, sizeof(isvisited)); 67 get_prime(); 68 int t; 69 scanf("%d", &t); 70 while(t --) { 71 memset(isvisited, false, sizeof(isvisited)); 72 scanf("%d %d", &star, &finish); 73 ans = bfs(); 74 if(ans == -1) printf("Impossible "); 75 else printf("%d ", ans); 76 } 77 return 0; 78 }