专栏文章
P13013 [GESP202506 五级] 奖品兑换 题解
P13013题解参与者 8已保存评论 7
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 6 条
- 当前快照
- 1 份
- 快照标识符
- @miozvi3g
- 此快照首次捕获于
- 2025/12/03 03:52 3 个月前
- 此快照最后确认于
- 2025/12/03 03:52 3 个月前
由于通过 和 两种方式均可兑换奖品,所以 的顺序显然是可以互换的。
暴力
显然,我们可以写出时间复杂度为 的暴力。
大致逻辑为:每次从两种券中选择数量较多的一种,花费较多的这种券来兑换奖品。
代码如下:
CPP#include <bits/stdc++.h>
using namespace std;
#define int long long
const int P=1e9+7;
const int N=1e5+10;
int n,m,a,b,ans;
signed main()
{
cin>>n>>m;
cin>>a>>b;
if(a<b)swap(a,b); //确保 a 较大
while(n>=a||m>=a)
{
if(n<m)swap(n,m);
if(m<b)break;
n-=a;
m-=b;
ans++; //从n,m中选择较大的变量减去较大的花费
}
cout<<ans<<endl;
return 0;
}
正解
注:下文中默认
的暴力显然会超时,考虑进行优化。
由于每次我们都让较大的变量减少的更多,所以在进行0次或多次兑换后, 两变量的差值一定会使下次操作后 。
具体地,令 ,则在进行 次兑换后,一定会有 或不可再进行兑换。
当 时,下次操作一定会使 且 ,于是再下次操作又会使 ,以此类推。
并且在进行两次操作后,由于 均减去了 ,操作后的 与开始的 大小相等。
因此,当 时,可以令 ,进行 次操作,具体看代码。
代码
CPP#include <bits/stdc++.h>
using namespace std;
#define int long long
const int P=1e9+7;
const int N=1e5+10;
int n,m,a,b,ans;
int s,d;
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>m;
cin>>a>>b;
if(a<b)swap(a,b);
if(a==b) //进行特判
{
cout<<min(n,m)/a<<endl;
return 0;
}
s=a+b,d=a-b;
while(n>=a||m>=a)
{
if(n<m)swap(n,m);
int x=(n-m)/d;
if(x==0) //当n-m<d时
{
int y=m/s;
ans+=y*2;
n-=y*s,m-=y*s;
x=2;
}
int v=min(n/a,min(m/b,x));
ans+=v,n-=v*a,m-=v*b;
if(m<b)break; //不可进行兑换
}
cout<<ans<<endl;
return 0;
}
可以证明,while 循环最多执行两次(最开始执行一次使 ,第二次就可兑换完)。
因此,此代码时间复杂度近似
相关推荐
评论
共 7 条评论,欢迎与作者交流。
正在加载评论...