arc139B - Make N 暴力

Link
思维 + 暴力 虽然很暴力但是很巧妙

题意

初始 P = 0 P=0 P=0, 你可以进行以下3种操作任意次,使得 P = N P = N P=N

  1. P + 1 P+1 P+1,花费 X X X
  2. P + A P+A P+A,花费 Y Y Y
  3. P + B P+B P+B,花费 Z Z Z

求最小花费。 ( 1 ≤ N , A , B , X , Y , Z ≤ 1 e 9 ) (1\leq N,A,B,X,Y,Z \leq 1e9) (1N,A,B,X,Y,Z1e9)

思路

首先令 y = min(y, a*x), z = min(z, b*x)
说一下官方解法
Y A ≤ Z B \frac{Y}{A} \leq \frac{Z}{B} AYBZ, 显然操作2最多进行 N A \frac{N}{A} AN 次,操作3最多进行 A − 1 A-1 A1 次,因为若操作3进行了 A A A 次,则它可以由 B B B 次操作2来代替,后者花费更少。
因为 m i n ( N A , A − 1 ) ≤ N min(\frac{N}{A},A-1) \leq \sqrt N min(AN,A1)N ,所以只要枚举小的那一个,并贪心地进行另一个操作,最后剩下的由操作1补全,即可得到最小花费
时间复杂度: O ( N ) O(\sqrt N) O(N )

本人并不是这么做的,但不会证明做法2333,
假设 a < b a < b a<b

  1. t = max(n / (a * b) - 1, 0),则对于 n n n t × a × b t\times a\times b t×a×b 这一部分,对花费的贡献是 min(y*b, z*a) * t注意这个地方要-1
  2. n -= t * a * b ,接下来计算剩余这部分的最小花费,考虑枚举操作3的执行次数,然后对再剩余的部分尽可能多执行操作2,最后剩余的部分执行操作1,对于每次枚举取最小值即可得到最小花费。

关于时间复杂度:
时间复杂度为步骤2中操作3的执行次数,也就是 n b \frac{n}{b} bn,其中 b = m a x ( a , b ) , n = n − ( n a b − 1 ) a b = n − ( m a x ( n − a b , 0 ) ) b = max(a, b),n = n - (\frac{n}{ab} - 1)ab = n - (max(n-ab, 0)) b=max(a,b)n=n(abn1)ab=n(max(nab,0)),当 b = n b = \sqrt n b=n 的时候, n b \frac{n}{b} bn 取到最大值 n \sqrt n n , 即时间复杂度为 O ( n ) O(\sqrt n) O(n )

代码

void solve() {
    ll n, a, b, x, y, z;
    cin >> n >> a >> b >> x >> y >> z;
    chmin(y, a * x);
    chmin(z, b * x);
    if(a > b) {
    	swap(a, b);
    	swap(y, z);
    }
    ll t = n / (a * b) - 1;
    chmax(t, 0);
    n -= t * a * b;
    ll ans = min(y*b, z*a) * t;
    ll delta = INF;
    for(int i = 0; i * b <= n; i++) {
    	ll j = (n-i*b) / a;
    	chmin(delta, i*z+j*y+((n-i*b)%a)*x);
    }
    cout << ans + delta << endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值