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

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=m xi>=0 xi (加法次数)最小,此时不用管 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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值