题解Luogu6022 快乐水
Posted cjtcalc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解Luogu6022 快乐水相关的知识,希望对你有一定的参考价值。
[ Preface ]
大概在半年前出过这道(((
然后当天读完这题,把自己写的 std 改了一下 ll 和特判信息交上去就 A 了。
捡了个大便宜。
[
Description
]
你一开始有 (n) 瓶快乐水。
有 (m) 个附属品,每喝一瓶快乐水就可以得到这 (m) 个附属品各 (1) 个,若有 (a[i]) 个附属品 (i) ,就可以再换一瓶快乐水。
问一共可以喝多少瓶快乐水。若可以无限白嫖就输出 Inf
。
[
Solution
]
一瓶一瓶处理快乐水显然是会 TLE 的,所以我们要批量处理快乐水。
(~)
我们开个桶 cnt[x]
表示 " 附属品 (x) 的数量 " 。
每次我们批量处理当前的 (n) 瓶快乐水:
- 令
ans += n
,表示喝掉了当前的 (n) 瓶快乐水。 - 令
cnt[i] += n
,表示得到了这 (m) 个附属品各 (n) 个。 - 令
n += cnt[i] / a[i], cnt[i] %= a[i]
,表示用把能换的快乐水都换了。
直到 (n=0) ,此时 (ans) 就是所求。
(~)
当然,还有无限白嫖快乐水的情况,在该情况下,(n) 永远不会等于 (0) ,也就是说快乐水会越喝越多了。
稍加分析一下我们发现:若不能无限白嫖,在任意时刻快乐水的数量不会大于等于初始给出的 (n) 。
想想看,如果可以无限白嫖,就相当于说,你用 (n) 瓶快乐水经过若干轮变换,换到了 (k) ((n leq k)) 瓶快乐水,那你再在这 (k) 瓶快乐水中选出 (n) 瓶快乐水再进行若干轮变换,又可以得到 (k) 瓶快乐水,如此往复,你总是可以白嫖快乐水。
于是就可以用上述性质判断是否无限白嫖快乐水了。
[
Code
]
#include<cstdio>
#define RI register int
using namespace std;
inline int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
const int N=100100,M=10;
int n,m,lim;
int a[N],cnt[M];
long long ans;
int main()
{
n=read(),m=read();
lim=n;
for(RI i=1;i<=m;i++)
a[i]=read();
while(n)
{
ans+=n;
for(RI i=1;i<=m;i++)
cnt[i]+=n;
n=0;
for(RI i=1;i<=m;i++)
n+=cnt[i]/a[i],cnt[i]%=a[i];
if(n>=lim)
{
puts("Inf");
return 0;
}
}
printf("%lld
",ans);
return 0;
}
[ Thanks for watching ]
以上是关于题解Luogu6022 快乐水的主要内容,如果未能解决你的问题,请参考以下文章
luogu题解 P1462 通往奥格瑞玛的道路二分+spfa