原题链接
http://codeforces.com/contest/940/problem/B
题目大意:
给你四个数字,n,k,a,b,拥有以下规则
1:(当n可以整除k时)每一步可以有两种选择
n/k
或
n-1
2:当你选择n/k时,费用+b
选择n-1时 ,费用+a
3:重复1,2直到n=1,输出费用;
题面
B. Our Tanya is Crying Out Loud
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Right now she actually isn’t. But she will be, if you don’t solve this problem.
You are given integers n, k, A and B. There is a number x, which is initially equal to n. You are allowed to perform two types of operations:
Subtract 1 from x. This operation costs you A coins.
Divide x by k. Can be performed only if x is divisible by k. This operation costs you B coins.
What is the minimum amount of coins you have to pay to make x equal to 1?
Input
The first line contains a single integer n (1 ≤ n ≤ 2·109).
The second line contains a single integer k (1 ≤ k ≤ 2·109).
The third line contains a single integer A (1 ≤ A ≤ 2·109).
The fourth line contains a single integer B (1 ≤ B ≤ 2·109).
Output
Output a single integer — the minimum amount of coins you have to pay to make x equal to 1.
Examples
inputCopy
9
2
3
1
output
6
inputCopy
5
5
2
20
output
8
inputCopy
19
3
4
2
output
12
Note
In the first testcase, the optimal strategy is as follows:
Subtract 1 from x (9 → 8) paying 3 coins.
Divide x by 2 (8 → 4) paying 1 coin.
Divide x by 2 (4 → 2) paying 1 coin.
Divide x by 2 (2 → 1) paying 1 coin.
The total cost is 6 coins.
In the second test case the optimal strategy is to subtract 1 from x 4 times paying 8 coins in total.
本人蒟蒻一枚,因此直到瞄了一眼某神犇的题解,由此有了思路
神犇题解:
http://shizhecheng.blog.163.com/blog/static/304640376201812594620665/?newFollowBlog
思路:一道裸贪心问题(不过我不明白为啥有大佬用DP),每次不要判断-1还是/k,而是每次都/k,若是无法整除k就让n减去n/k的余数再除;否则/k(费用统一处理)
代码
#include<bits/stdc++.h>
#define ll long long//个人爱好
using namespace std;
ll n,k,a,b;
ll coin;//费用
int main() {
ios::sync_with_stdio(false);//据说可以关闭cin,cout与scanf,printf的同步,提升运行速度
cin>>n>>k>>a>>b;//输入
if(k==1) {//特判,如果k=1那么直接输出一直-1的结果(n/1=n若无此特判卡第6,12,23,37,44测试点,亲身经历)
cout<<a*(n-1)<<endl;
return 0;
}
while(n!=1) {//循环条件:n>1
if(n<k) {//如果(n<k)即无论如何都无法执行广义的n/k操作
coin+=(n-1)*a;//直接将剩下的使用-1操作
n=1;
continue;//这两句可使用break代替
}
ll v=n/k;//long long为(长)整形,整形/整形=整形 利用了整形的性质
if(n%k) {//无法整除
ll m=n%k;//n/k的余数
coin+=min(m*a+b,(n-v)*a);//一减一除也许还不如一直减,进行最小值判断
//注意,此处的m*a+b与(n-v)*a都是费用,是两种不同方案的费用
//与操作/k或-1无关,执行只有一个结果,那就是n=n/k;
//这里只是两种操作方式不同的费用,亲身体验过混淆的感觉
} else//可以整除
coin+=min((n-v)*a,b);//同上,在/与-之间选择最小费用
n/=k;//每次使n/k,即时间复杂度为O(logn(以k为底))
}
cout<<coin<<endl;//输出
return 0;//程序要休息喽
}