B. Our Tanya is Crying Out Loud(cf)and 5918: 改变(中石油)
cf:Our Tanya is Crying Out Loud
这两道题很相似,可以用同一种方法解出。
假设初始从s到t ,经过 +a 或 *b实现,可以写出:t=pow(b,n)*s+m*a
枚举n(不会超过log(s-t)个),从而求出m;
让a[i]的和尽可能小,即b[i]尽可能大;
从pow(b,n)-->pow(b,0) 一直到m为0,结束
cf code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll llf=(1ll<<63)-1; int main() { ll t,a,b,k; cin>>t>>k>>a>>b; if(k==1) { cout<<(t-1)*a<<endl; return 0; } ll ans=llf,n=0,B=1; while(t-B>=0) { ll m=(t-B),ant=n*b,up=B; while(m) { ant+=(m/up)*a; m%=up; up/=k; } ans=min(ans,ant); n++; B*=k; } cout<<ans<<endl; return 0; }
cf 也可以贪心,能除尽可能除
代码如下:
#include <bits/stdc++.h> #define shutdown std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); using namespace std; typedef long long ll; int main() { ll n,a,b,k; shutdown cin>>n>>k>>a>>b; if(k==1) { cout<<(ll)(n-1)*a<<endl; return 0; } ll ans=0; while(n!=1) { if(n%k) { if(n>k) { ans+=n%k*a; n=n-n%k; } else { ans+=(n-1)*a; n=1; } } else { ans+=min((n-n/k)*a,b); n/=k; } } cout<<ans<<endl; return 0; }
中石油 code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll llf=(1ll<<63)-1; int main() { ll s,t,a,b,B=1; ll ans=llf,n=0; scanf("%lld%lld%lld%lld",&s,&t,&a,&b); while(t-B*s>=0) { if((t-B*s)%a==0) { ll m=(t-B*s)/a,ant=n,up=B; while(m) { ant+=m/up; m%=up; up/=b; } ans=min(ans,ant); } n++; B*=b; } printf("%lld\n",ans); return 0; }