题解:P14974 [USACO26JAN1] Chip Exchange B
wwwidk1234 · · 题解
为什么感觉这场比赛 C<A<<<<<B 呢?本来估计可以 AK 然后直接飞升 Silver 的,结果被 B 神秘 Ad-hoc 创飞了 /fn
博客园 USACO 2026 Jan1 Bronze
以下记“B->A”为把 B 换成 A。
题目要求的是 A,你首先想着 B->A 能不能多增加。首先显然是把能换的都换了。
然后既然收到的芯片是随机的,所以肯定是运气最坏的情况,直观理解就是,你收到的芯片换成目标芯片 A 是最不值的那一种。所以就要分类讨论:
- 如果 B 换成 A 不亏不赚(
c_A=c_B ),那么最坏情况就是先给你一大堆 B,恰好可以全部换成 A;等到 A 差一次交换的就达到f_A 的时候,把 A 补到f_A-1 ,剩下这一个 A 肯定就是给你c_B 个 B,让你用c_B 个 B 换成c_A 个 A。 - 如果 B 换成 A 会亏(
c_B>c_A ),那么最坏情况就应该是给芯片 B 要多一点,先给一大堆 B,用这些 B 恰好完全换成 A;等到 A 差一次交换的就达到f_A 的时候,就把 A 补到f_A-1 ,剩下这一个 A 同理情况 1,给你c_B 个 B,让你用c_B 个 B 换成c_A 个 A。 - 如果 B 换成 A 会赚(
c_B<c_A ),那最坏情况:一直给 A 到达到f_A 之前1 个,然后给 B 补充到c_B 个,用这c_B 个 B 去换c_A 个 A。
难点在于就是分类讨论,剩下的式子应该很好推,简单模拟即可。难度黄左右。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
constexpr int N=-1;
ll a,b,ca,cb,f;
ll cnt=0; //交换次数
inline void changeall()
{
cnt=(b/cb); b-=cnt*cb,a+=cnt*ca;
}
inline ll solve()
{
cin>>a>>b>>ca>>cb>>f;
ll ans=0;
changeall();
if(a>=f) return 0;
cerr<<a<<' '<<b<<endl;
if(ca==cb)
{
cnt=(f-a)/ca; if((f-a)%ca==0) cnt--;
ans+=cnt*cb-b; b+=cnt*cb-b;
changeall();
// cerr<<cnt<<' '<<a<<' '<<b<<endl;
ans+=(f-a-1);
ans+=cb;
}
else if(cb>ca)
{
cnt=(f-a)/ca; if((f-a)%ca==0) cnt--;
ans+=cnt*cb-b; b+=cnt*cb-b;
changeall();
ans+=(f-a-1);
ans+=cb;
}
else
{
ans+=(f-a-1);
ans+=cb-b;
}
return ans;
}
int main()
{
// freopen("neuvillette.in","r",stdin);
// freopen("neuvillette.out","w",stdout);
cin.tie(0)->sync_with_stdio(0);
int T;
cin>>T;
while(T--) cout<<solve()<<'\n';
return 0;
}
/*
- 标题 『Problem 1. Chip Exchange』
- 链接 『https://usaco.org/index.php?page=viewproblem&cpid=1527&lang=en』
- 时限 『4000 ms』
- 用时 『h 40min』
- 思路:
题目要求的是A,看看cb B->ca A能不能多增加
先把能换的都换了,更新a,b
假如B换成A不亏不赚,那最坏情况应该就是先给你一大堆B可以全部换成A,等到A差一点点的时候又给你一大堆B
aA bB cB->cA fA
然后补B,补充到floor((f-a)/c)*c,全部变成A,更新a,b=0
然后给A:(f-a-1)
然后给B:c,换成A
假如B换成A会亏(cb>ca),那最坏情况应该就是给一大堆B,然后用这些B换成A,换到再换一次A就达标了为止
B恰好完全反应,给A,更新a,b=0
然后给A补到达标-1,给Bcb个
假如B换成A会赚(cb<ca),那最坏情况:一直给A到达标之前1个,然后给B (cb-b) 个,用B去换A
*/