1 条题解
-
0
自动搬运
来自洛谷,原作者为

WhitD
%$@oma搬运于
2025-08-24 22:49:35,当前版本为作者最后更新于2023-09-14 20:26:25,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题目大意
给定两个正整数 和 ,您可以进行以下两种操作任意次(包括零次):
- 选择一个整数 满足 ,将 变为 。该操作每次花费 枚金币,每次选择的整数 可以不同。
- 将 变为 。该操作每次花费 枚金币。其中 表示小于等于 的最大整数。
给定正整数 ,求将 变为 的倍数最少需要花费几枚金币。
思路
我们发现,先乘再除对结果是没有影响的(因为操作一加的值小于 ,操作二的除法向下取整就把多加的数也除掉了),因此一定是先除再乘。
我们假定当前的数为 ,将它进行一次操作一:如果乘完了不加数,它会变成 ;如果乘完后加数,最多可以加 ,也就是 ,它会变成。这说明 进行完操作一后可以变到的范围是 。
于是我们可以先枚举出进行操作二的次数(这个过程是 的),同时进行重复进行操作一直到 成为 的倍数(根据区间端点来判断是否在区间内),然后计算总代价,全局取 就可以了。
注意特判 是无解的。
AC 代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; int T; int main() { cin>>T; while(T--) { ll n,k,m,a,b,ans=114514191981011451; cin>>n>>k>>m>>a>>b; if(n%m==0) { cout<<0<<endl; continue; } if(k==1) { cout<<-1<<endl; continue; } for(ll i=0,d=0;;i++,n/=k,d=i*b) { if(!n) { ans=min(ans,b*i); break; } __int128 l=n,r=n; while(l%m&&(r/m==l/m)) { r=r*k+k-1; l*=k; d+=a; } ans=min(ans,d); } cout<<ans<<endl; } return 0; }
- 1
信息
- ID
- 9096
- 时间
- 4000ms
- 内存
- 1024MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者