zoukankan      html  css  js  c++  java
  • P6022 快乐水 题解

    CSDN同步

    原题链接

    简要题意:一开始你有 (n) 瓶快乐水,每拥有 (1) 瓶快乐水就可以附带 (n) 个物件,第 (i) 个物件有了 (a_i) 个就可以 再获得 (1) 瓶快乐水。不允许借代 / 赊账,求最多得到的快乐水的瓶数,如果是无限多则输出 ( ext{Inf}).

    这是洛谷一道月赛题的 (T1).

    首先,本人赛时并没有想很多,当时只想着: (T1) 应该是水模拟吧,可是当时仔细想:(m = 5) 万一死循环陷入环内,怎么办?万一 ( ext{Inf}) 情况判不出来,怎么办?万一被卡出 ( ext{TLE}) 怎么办?

    但是我不心慌,决定一一解决。

    实则真正意义上的模拟,是那种 一眼看起来就是模拟水题,然后直接乱发过掉 的,而不是 通过一定量思考发现可以模拟解决再过掉 的,本题被评为橙题是不应该的,不应该。

    死循环陷入环内这一问题是最棘手的。但是仔细想:每次 你得到的快乐水瓶数只会越来越多,越来越多,从来不存在少的情况。如何判断结束呢?一个快乐水也衍生不出来就可以结束了。

    那么如何判断无限情况呢?很显然,无限 当且仅当所有 (a_i) 相等 且 (a_i leq n). 为什么呢?因为,如果所有 (a_i) 都相等并且第一次可以衍生的话,首先 之后每次操作 (a_i) 都相等,然后每次衍生出的 (m) 个都会再产生,再产生 (cdots cdots) 所以是无限的,具体不懂可以看看样例。

    这一切都解决之后,我们想一想 ( ext{TLE}) 问题该怎么办?

    可是你想想,真会 ( ext{TLE}) 么?

    我们需要构造一组数据使得借和还的次数最多!

    这里美妙优秀的 ( ext{WYXkk}) 出题人给出了一组美妙无比的 ( ext{hack}) 数据:

    10000 5
    2 3 7 43 1807
    

    其构造方法在于,(a_i = Big( prod_{j=1}^{i-1} a_j Big) + 1),并且 (a_i = 2).

    经过实测,这个数据会达到 (2.8 imes 10^7) 次!(答案达到 (3 imes 10^{10}),需要部分开启 ( ext{long long})

    当然如果 (m=6) 模拟就无力解决啦。

    时间复杂度:(O( ext{wys})).(大概很优秀吧)

    实际得分:(100pts).

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0;while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x*f;}
    
    int n,m; long long ans=0;
    int a[6],b[6],c[6];
    
    long long l;
    bool x=0; //无限情况
    inline void check(){
    	for(int i=1;i<=m;i++)
    		if(b[i]>=a[i]) l+=b[i]/a[i],b[i]%=a[i];
    } //当前瓶数为 b , a 是初始数组 , l 记录多出来的瓶数
    
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=m;i++) a[i]=read(),b[i]=n;
    	ans+=n;
    	while(1) {
    		for(int i=1;i<=m;i++) c[i]=b[i];
    		l=0; check();
    		if(!l) break;
    		ans+=l;
    		for(int i=1;i<=m;i++) b[i]+=l; //记录答案,重新衍生
    		bool f=0;
    		for(int i=1;i<=m;i++) if(c[i]-b[i]) {f=1;break;} //做标记
    		if(!f) {x=1;break;} //如果 c[i] = b[i] 则说明一次之后根本没变 , 是无限情况
    	}
    	if(x) printf("Inf"); else
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    centos-docker安装及基本使用
    List集合-03.Vector
    List集合-02.LinkedList
    List集合-01.ArrayList
    常用图像处理方法
    git使用
    bug记录
    bash vim等常用命令
    python常用
    MTCNN试用
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12727720.html
Copyright © 2011-2022 走看看