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=T−bnSa
剩下的问题是求
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);
}