[CSP校内集训]A(进制)

题意

给一个数\(S\),可以加\(a\)或者乘\(b\),问最少多少次操作到\(T\),无解输出-1,\((1\leq a\leq 10^9,2\leq b\leq 10^9)\)

思路

刚刚看到像跳楼机,但是a,b较大于是放弃(说不定可以乱胡呢?);当然直接建图也有30分的好成绩(

即使\(a,b\)交替操作,最终状态仍然可以化成\(T=S\times b^y + a\times x\)的形式

枚举\(y\),最多不超过\(logn\)种,一个\(y\)对应一个\(x\),需要对\(x\)进行\(b+1\)进制拆分,且每一位加起来的数最小

从高位到低位贪心即可完成拆分操作,整个算法的时间复杂度为\(O(log^2n)\)maybe

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s,t,a,b,ans=(1LL<<60);

ll qpow(ll a,ll b)
{
    ll ret=1;
    while(b)
    {
        if(b&1) ret=ret*a;
        a*=a;
        b>>=1;
    }
    return ret;
}
ll find(ll x,ll y)
{
    ll ret=0;
    for(int i=x;i>=0;--i)
    {
        ll po=qpow(b,i);
        ret+=y/po;
        y%=po;
    }
    return ret;
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%lld%lld%lld%lld",&s,&t,&a,&b);
    for(ll i=0;i<=32;i++)
    {
        ll x=t-s*qpow(b,i);
        if(x<0) break;
        if(x%a) continue;
        ll need=x/a;
        ll st=find(i,need);
        if(st) ans=min(ans,i+st);
    }
    if(ans==(1LL<<60)) ans=-1;
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Chtholly/p/11798674.html