集训Day 3
A题:
B题:
比赛开始,直接跟着A题的样例开搞,成功拿下题目(get100pt),B题我写了一个肯定会爆的桶,后来为了多拿分就将数组开大了亿点然后就炸了痛失了B题15pt以及前三。(哭)
改题的时候依旧不严谨,B题订正时脑袋里想的是if else 的写法 实际写的是 if判断后未加return 0导致输出重复的做法。
不严谨了两天了,第一天因为提交前没重新运行一遍挂了一次,今天又来了一次。
TIPS: 1. 值域过大时不宜用桶,1e8 个 int = 380MB 2. 做题时思路略显粗糙,要加强对于知识点的练习和写模板 3. gcd 具有「可重复贡献性质」,区间 gcd 和区间最大值一样需要使用 ST 表(Bonus: gcd 本质上是对指数取 min) 4. 计算机四种存储器:硬盘、RAM(内存)、Cache(高速缓存)、Register(寄存器),速度逐渐变快,空间逐渐变小 5. 位、字节、KB、MB、GB 的转换关系(练习:1e7 的 int 数组占多少内存?保留两位小数) 6. 二叉搜索树:每个节点内有数字,满足性质一:中序遍历是递增的,性质二:左子树都小于自己,右子树都大于自己 7. n 个物品中有一件次品,已知这件次品轻一些,使用天平分三份称量;(Bonus:如果不知是轻是重如何称量?) 8. 组合数学从不同角度出发均可得到答案,例如三份代码四人写,两人有矛盾不能一起,问方案数,可以从代码的角度出发考虑哪个代码放两人,可以从人的角度出发考虑哪个人落单了 9. 100 以内的质数有 25 个 10. 欧拉筛保证每个数只会被自己的最小质因子筛到一次,所以是 O(n) 的 11. 每过一年星期数+1,闰年+2 12. 一行组合数加起来是 2 的次幂,也即 C(n, 0) + ... + C(n, n) = 2^n(Bonus:这个式子有什么组合意义?) 13. 判断 T 是否是 S 的子序列,可以直接 O(|S|) 的硬匹配,也可以预处理好 S 的 Pos[i][j] 数组后 O(|T|) 地匹配
B题题解:
首先,当n=1答案一定为1e9。(在程序开头做特判即可)
再来仔细阅读题目即可发实擦去之后填入新的只是一个幌子,本质上是在要求你擦掉一个数字之后其他所有数的最大公因数。那么我们就可以写出偏向暴力的程序,但为了追求更好,我们此时可以发现就是在数组内选一个点使得其左右两边的所有数公共因数最大,那么接下来我们可以发现我们可以通过前、后缀和来优化暴力中的求余下的数的gcd就可以得到正解。
B题代码:
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,a[N],p[N],s[N]; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } int main() { ios::sync_with_stdio(false); cin>>n; if(n==1) { cout<<"1000000000"; return 0; } for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) p[i]=gcd(a[i],p[i-1]); for(int i=n;i;i--) s[i]=gcd(a[i],s[i+1]); int ans=0; for(int i=1;i<=n;i++) ans=max(ans,gcd(p[i-1],s[i+1])); cout<<ans; return 0; }
A题代码:
#include<bits/stdc++.h> using namespace std; long long a,b,c,d; int main() { ios::sync_with_stdio(false); cin>>a>>b>>c>>d; long long t2=a*c,t3=a*d,t4=b*c,t5=b*d; cout<<max(max(t2,max(t2,max(t3,t4))),max(t5,t2)); return 0; }