旅行前的准备 pta

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值