【ISA的胡策】联校11.7(数学相关)

本文介绍了一种通过加法和乘法操作将初始数值S转换为目标数值T的算法,并给出了解决方案。算法通过枚举指数n来找到最短路径,确保在允许的操作下达到目标值所需的最少操作次数。

T1:

一开始你有一个数S,你可以通过两种操作改变这个数的值:
给这个数加a
给这个数乘b
求最少通过多少步可以将S变成T

1<=S < T<=1e9
1<=a<=1e9
2<=b<=1e9

题解:

考场上bfs30分+exgcd乱搞又得30分
一开始我认为T=(S+xa)*yb+za,使x+y+z最小,但是忽视了S+xa之后还能除b的过程,所以全是-1
这样下去不是没完了?减完了还能除,除完了还能减
不如更加简化一下,一定存在n,m使T=bnS+ma
我们枚举n的值,可以发现n只有logT种取值,此时可以算出m=TbnSa
剩下的问题是求xi使ni=0xibi=mxi>=0xi(加法次数)最小,此时不用管bi的计算次数,因为在你计算bnS时只要i比n小,随便找几个空把xi塞进去就好咯
要想让加法次数最小,就是让m尽早被分完,所以先分大的(b^n),再分小的(b^0),贪心选择
复杂度O(log2T)

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#define INF 1e9
#define LL long long 
using namespace std;
int num=0,S,T,a,b;
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d%d%d",&S,&T,&a,&b);
    LL ans=INF,nowb=1,n=0;
    while (1)
    {
        LL t=T-nowb*S;
        if (t<0) break;
        if (t%a==0)
        {
            LL m=t/a,tot=n,up=nowb;
            while (m)
            {
                tot+=m/up;
                m%=up;
                up/=b;
            }
            ans=min(ans,tot);
        }
        n++;
        nowb*=b;
    }
    if (ans==INF) printf("-1");
    else printf("%d",ans);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值