51Nod 3016 Prime Path

阿P给阿K出了一个难题,他给阿K两个素数A,B,保证A,B的位数相同且为4位或5位。

阿K只能对A作一种操作,即将其中一位数字改成另一个数字,要求每次操作后得到的数还是一个素数,问最少多少次可以从A变到B

输入

第一行一个整数n,代表有n组数据
对于每组数据,输入一行两个四位或五位素数A,B

输出

对于每组数据输出一行,表示最少的操作次数
无解输出No solution

数据范围

对于50%的数据:A,B为四位素数
对于100%的数据: A,B的位数不超过五位,n<=20

输入样例

输入样例1:

1
1033 8179

输入样例2:

1
1373 8017
输入样例3:
1
1033 1033

输出样例

输出样例1:
6
输出样例2:
7
输出样例3:
0

参考答案

#include<stdio.h>
#include<set>
#include<iostream>
#include<stack>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
typedef long long ll;
typedef long double ld;
typedef double db;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int mod=998244353;
ll mo(ll a,ll p) {
	return a>=p?a%p:a;
}
inline int rd() {
	int x = 0, f = 1;
	char ch;
	while (ch < '0' || ch > '9') {
		if (ch == '-')f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return f * x;
}
inline ll gcd(ll x, ll y) {
	return y==0?x:gcd(y,x%y);
}
inline ll speed(ll a,ll b) {
	ll cur=a,anss=1;
	while(b) {
		if(b&1) anss=anss*cur;
		cur=cur*cur;
		b>>=1;
	}
	return anss;
}
const int MAXN=1e5;
bool ipr[MAXN+20];
int cnt,pri[MAXN/5];
void prime() { //埃式筛法
	int N=sqrt(MAXN)+0.5,mul;
	memset(ipr,true,sizeof(ipr));
	ipr[1]=false;
	for(int i=2; i<=N; i++) {
		if(ipr[i]==true) {
			i==2?mul=1:mul=2;
			for(int j=i*i; j<=MAXN; j+=i*mul) {
				ipr[j]=false;
			}
		}
	}
	for(int i=2; i<=MAXN; i++) {
		if(ipr[i]==true) {
			pri[++cnt]=i;
		}
	}
}
int T,a,b;
int wei(int x) {
	int ret=0;
	do {
		x/=10;
		ret++;
	} while(x);
	return ret;
}
struct E {
	int num,cnt;
};
bool f[100020];
int bits[10];
int comb(int t) {
	int ret=0;
	for(int i=t; i>=1; i--) {
		ret*=10;
		ret+=bits[i];
	}
	return ret;
}
int bfs() {
	int t=wei(a);
	queue<E>q;
	q.push((E) {
		a,0
	});
	f[a]=true;
	while(!q.empty()) {
		E cur=q.front();
		q.pop();
		if(cur.num==b) return cur.cnt;
		for(int i=1; i<=t; i++) {
			bits[i]=cur.num%10;
			cur.num/=10;
		}
		//cout<<comb(t)<<endl;
		for(int i=1; i<=t; i++) {
			int d=bits[i];
			for(int j=0; j<=9; j++) {
				if(j==d||(i==t&&j==0)) continue;
				bits[i]=j;
				int nex=comb(t);
				//cout<<nex<<endl;
				if(ipr[nex]&&!f[nex]) {
					f[nex]=true;
					q.push((E) {
						nex,cur.cnt+1
					});
					//cout<<nex<<endl;
				}
			}
			bits[i]=d;
		}
	}
	return -1;
}
int main() {
	io_opt;
	prime();
	cin>>T;
	while(T--) {
		memset(f,false,sizeof(f));
		cin>>a>>b;
		if(a==b) {
			cout<<0<<endl;
			continue;
		}
		int ans=bfs();
		if(ans==-1) {
			cout<<"No solution"<<endl;
		} else {
			cout<<ans<<endl;
		}
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值