Codeforces Round #466 (Div. 2) B. Our Tanya is Crying Out Loud[将n变为1,有两种方式,求最小花费/贪心]
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.
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 a single integer — the minimum amount of coins you have to pay to make x equal to 1.
9
2
3
1
6
5
5
2
20
8
19
3
4
2
12
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.
[题意]:将n变为1,有两种方式① n-1花费a , ② 如果n能够被k整除,n=n/k,花费b.求最小花费.
[分析]:很显然这是道贪心题,
一个很容易错的地方就是想着优先除二,然后在减一,
因为没有考虑两者的花费,如果b很大的话就错了,所以每次都要判断下,然后注意细节就行了
首先如果k==1,那么ans=(n-1)*a;
n%k!=0,只能执行操作1
n<k,只能执行操作1
n%k==0(n>=k) 的情况下比较n到达相同结果时两种操作的花费即可。
[代码]:
/* 题意:将n变为1,有两种方式①n-1花费a,②如果n能够被k整除,n=n/k,花费b,求最小花费 */ /* 很显然这是道贪心题, 一个很容易错的地方就是想着优先除二,然后在减一, 因为没有考虑两者的花费,如果b很大的话就错了,所以每次都要判断下,然后注意细节就行了 */ #include<bits/stdc++.h> using namespace std; #define pb push_back #define mem(a) memset(a,0,sizeof(a)) typedef long long ll; typedef pair<int,int> pii; const int maxn=150; const int inf=0x3f3f3f3f; int main() { ll x,n,k,a,b,ans; while(~scanf("%lld%lld%lld%lld",&n,&k,&a,&b)){ ans=0; if(k==1) return 0*printf("%lld\n",a*(n-1)); //注意特判k==1的情况,防止死循环 while(n!=1){ //n无法整除k if(n%k!=0){ //不能整除只能减法(a),减到整除为止 ans+=a*(n%k); n-=(n%k); } if(n<k){ //此时只能减法(a),除法永远用不到,直接求解答案 ans+=a*(n-1); break; } //n可以整除k ans+=min(b,a*(n-n/k)); //减法(a)和除法(b)取最小花费 n/=k; //n可以整除k } printf("%lld\n",ans); } } /* n-n/k*k = n%k 获取距离n最近的k的倍数的方法是:n/k*k = n-n%k */