D - 整数变换问题

整数变换问题
题意:问我们最少经过多少次变换可以将n转化为m。
题解:这个题我们很容易想到就是用dfs,但是数据范围也很明显不能用直接的暴力,所以我们需要剪枝。
我们假设用最原始的暴力,就是每次循环两种情况一直到最后。这样的暴力很机械,很盲目,我们必须找到所有的情况才能结束,因为只有所有的情况都出现了,我们才能判断出最少的步数是多少。但是如果我们先确定步数,也就是让这个代码走那么多步,看能否达到预定的情况,这样我们就少走了那些,这样是要优于纯暴力的。
下面是具体的代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
char s[200];
int len;//字符数组的长度
int maxsum;//所走的最大步数
int cal(int i,int n)
{
    if(i==0)
        return 3*n;
    else
        return n/2;
}
int dfs(int step,int n,int m)
{
    if(step>maxsum)
        return 0;
    for(int i=0;i<2;i++)
    {
        int num=cal(i,n);
        if(num==m||dfs(step+1,num,m))//dfs返回1说明匹配到n==m
        {
            if(i==0)
            {
                s[len++]='f';
            }
            else
            {
                s[len++]='g';
            }
            return 1;
        }
    }
    return 0;
}
int main()
{
    int n,m;
    cin>>n>>m;
    len=0;
    maxsum=1;
    while(!dfs(1,n,m))//达到剪枝效果
    {
        maxsum++;
    }
    cout<<maxsum<<endl;
    for(int i=0;i<len;i++)
    {
        cout<<s[i];
    }
    cout<<endl;
    return 0;
}

代码中的maxsum就是为了剪枝,我们判断当前的步数能否达到最终结果,这样假设能达到的话就直接推出while循环了。这样就大大减少了走的步数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值