LX同学想要游遍整个中国甚至全世界!所以这个国庆假期她计划去长沙玩。但是在她做旅行前的准备的时候,她收到了老师的作业,并且要求在国庆假期结束之前上交!LX同学非常的生气,告诉了你这个消息。你也觉得实在是太过分了,但是没有办法,只好帮助LX同学完成她的作业。
老师给了LX同学两个整数,分别是 x 和 y 。每次LX同学可以从中选择一个数 num ,把这个数变成 (num+2) mod p 或 (num∗2) mod p 或 (num∗num) mod p ,请问,最少需要多少次操作,能使这两个整数相等。
输入格式:
一行三个正整数 x,y,p(3≤p≤106,1≤x,y<p) ,保证p 是一个奇数。
输出格式:
一行一个整数表示最少操作次数。
样例1
输入样例
3 4 5
输出样例
1
样例2
输入样例
2 3 5
输出样例
2
提示
样例一解释:3∗3≡4(mod5) 。
样例二解释:3∗2≡1(mod5) ,1∗2≡2(mod5) 。
代码
#include <algorithm> //7-8 旅行前的准备 (25分)
#include <climits>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 1e6 + 2;
typedef long long ll;
ll p;
ll disx[maxn], disy[maxn]; //分别为x, y到顶点i的最短路长度交点
bool vis[maxn];
struct node {
ll v, k;
};
int bfs(ll x, ll y) {
queue<node> q;
q.push({x, 0});
memset(vis, false, sizeof(vis));
vis[x] = true;
while (!q.empty()) {
ll v = q.front().v;
ll k = q.front().k;
disx[v] = k;
// cout << v << " " << disx[v] << endl;
if (v == y) break;
q.pop();
if (!vis[(v + 2) % p]) {
vis[(v + 2) % p] = true;
q.push({(v + 2) % p, k + 1});
}
if (!vis[v * 2 % p]) {
vis[v * 2 % p] = true;
q.push({v * 2 % p, k + 1});
}
ll t;
t = v * v % p;
if (!vis[t]) {
vis[t] = true;
q.push({t, k + 1});
}
}
memset(vis, false, sizeof(vis));
while (!q.empty()) q.pop();
q.push({y, 0});
vis[y] = true;
while (!q.empty()) {
ll v = q.front().v;
ll k = q.front().k;
disy[v] = k;
if (v == x) break;
q.pop();
if (!vis[(v + 2) % p]) {
vis[(v + 2) % p] = true;
q.push({(v + 2) % p, k + 1});
}
if (!vis[v * 2 % p]) {
vis[v * 2 % p] = true;
q.push({v * 2 % p, k + 1});
}
ll t;
t = 1LL * v * v % p;
if (!vis[t]) {
vis[t] = true;
q.push({t, k + 1});
}
}
ll ans = INT_MAX;
for (int i = 1; i < p; i++)
if (disx[i] >= 0 && disy[i] >= 0) ans = min(ans, disx[i] + disy[i]);
return ans;
}
int main() {
memset(disx, -1, sizeof(disx));
memset(disy, -1, sizeof(disy));
ll x, y;
cin >> x >> y >> p;
cout << bfs(x, y) << endl;
system("pause");
return 0;
}