整数变换问题

整数变换问题

SDUTOJ 整数变换问题
Problem Description
整数变换问题。关于整数i的变换f和g定义如下:f(i)=3i;
试设计一个算法,对于给定的2 个整数n和m,用最少的f和g变换次数将n变换为m。例如,可以将整数15用4 次变换将它变换为整数4:4=gfgg(15)。当整数n不可能变换为整数m时,算法应如何处理?
对任意给定的整数n和m,计算将整数n变换为整数m所需要的最少变换次数。
Input
输入数据的第一行有2 个正整数n和m。n≤100000,m≤1000000000。
Output
将计算出的最少变换次数以及相应的变换序列输出。第一行是最少变换次数。第2 行是相应的变换序列。
Sample Input
15 4
Sample Output
4
gfgg
Hint

Source

该问题乍一看没有什么头绪,最少变换次数怎么找???
是不是比m大就得进行除操作,比m小就得进行乘操作??
在不确定是不是最优解的情况下怎么把操作符加入队列???
问题解决思路:
用DFS进行探索,但是每次只探索一层,两种操作都进行
找到的第一个匹配的结果即为所求的解。
找到最优解后,进行回溯,在回溯的过程中把之前走过的路径加入队列
即可得到最优解的路径。
搜索树和代码如下:

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define N 25
#define inf 0x3f3f3f3f
int n, m;
//定义k来表示搜索树的深度
int k = 1;
//定义一个队列来存放各类操作
queue<char> q;
bool DFS(int x, int n)
{
    //防止死循环,保证最多只能访问到下一层
    if(x > k)
        return false;
    //找到返回true
    if(n == m)
        return true;
    //这里必须用一个temp做临时变量
    //若不用temp做临时变量,回溯的时候n的值发生变化
    //导致结果异常
    int temp = n;
    //左右都做一遍,看看能否到达目的
    for(int i = 0; i < 2; i++)
    {
        if(i == 0)
            temp = n * 3;
        else
            temp = n / 2;
        if(DFS(x+1, temp))
        {
            if(i == 0)
                q.push('f');
            else
                q.push('g');
            //这里必须要return true 
            //因为只需要找到第一个满足条件的那条路径
            //回溯返回的时候把路径上的运算加入队列即可。
            return true;
        }
    }
    //如果没找到返回false,k++
    //可往更深一层探索
    return false;
}
int main()
{
    cin >> n >> m;
    //找不到,往更深一层探索!
    while(!DFS(0, n))
        k++;
    cout << k << endl;
    while(!q.empty())
    {
        cout << q.front();
        q.pop();
    }
    return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
整数变换问题指的是,给定两个整数 a 和 b,允许执行以下两个操作之一: 1. 将 a 加上 b 的值; 2. 将 b 加上 a 的值。 求通过若干次这两个操作,能否将 a 变换成 b。 正确性证明如下: 首先,我们可以证明,对于任意两个正整数 a 和 b,它们能够通过若干次操作变换到一起,当且仅当它们的最大公约数能够整除它们的差值。 证明如下: 设 a 和 b 的最大公约数为 d,则 a = d * x,b = d * y,其中 x 和 y 互质。 假设我们通过若干次操作将 a 变换成 b,变换过程中,a 和 b 分别变换成了 a' 和 b'。则有: a' = a + k * b = d * x + k * d * y = d * (x + k * y) b' = b + m * a = d * y + m * d * x = d * (y + m * x) 其中 k 和 m 均为非负整数。 由于 x 和 y 互质,因此 x + ky 和 y + mx 也是互质的。因此,如果 a 和 b 能够通过若干次操作变换到一起,那么必然存在非负整数 k 和 m,使得 x + ky = y + mx。 将其变形得: (k - m) * y = (x - y) * m 由于 x 和 y 互质,因此 x - y 和 y 是互质的,因此必然存在 m 的逆元 m',使得 m' * (x - y) ≡ y (mod k - m)。 因此,我们可以取 k = m + m' * (x - y),得到一个满足条件的 k。此时,我们可以通过若干次操作将 a 变换成 b。 反之,如果 a 和 b 的最大公约数不能整除它们的差值,那么显然无法通过若干次操作将 a 变换成 b。 因此,我们可以通过检查 a 和 b 的最大公约数是否能够整除它们的差值,来判断它们能否通过若干次操作变换到一起。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值