2020.11.02【NOIP提高A组】模拟 比赛总结

10 篇文章 0 订阅
8 篇文章 0 订阅

比赛地址

https://gmoj.net/senior/#contest/home/3245

题目

6843. 【2020.11.02提高组模拟】移形换影
6844. 【2020.11.02提高组模拟】旅途和生活
6845. 【2020.11.02提高组模拟】梯度弥散
6846. 【2020.11.02提高组模拟】旅人1970

总结

这次会做前3题(准确来说是2.5题,因为T2的结论不会证明),然而却只有184分,只切了T3,后来发现犯了不少低级错误。

T1

一道繁琐的模拟题。为了方便处理,可以只把0和2放进序列里,把1挂在后面的数字上,后面的数字只用记录前面1的个数就好了;此外,还要在结尾多放一个2(如果是0,就有可能会被拉到前面去)。

比如说序列 1   0   0   2   1   0   1   1   2   0   1 1\, 0\, 0\, 2\, 1\, 0\, 1\, 1\, 2\, 0\, 1 10021011201会变成 1 0   0   2   1 0   2 2   0   1 2 _10\, 0\, 2\, _10\, _22\, 0\, _12 10021022012

接着从左往右扫。如果当前数字是2,就把后面离它最近的1拉到它前面,拉不动就算了;如果当前数字是0,就把它前面的1移到它后面的第一个2的前面,就算移不过去也要移动。

结果WA 60了……

后来发现是处理0时有问题: 2 00002 _200002 200002在动2步后最优的情况应该是 0 2 0002 0_20002 020002而不是 1 0 0 1 002 _100_1002 1001002
因此如果当前数字是0,直接把它前面的1搬到后面就行了(每次只把它自己和前面的1交换)。

T2

本来是没什么思路的。但是我看到了这句话:
在这里插入图片描述
而上表说3,4,5,6保证a和b都是奇数(证明在https://blog.csdn.net/huangzihaoal/article/details/109477724)。
我们可以先把a和b都写成 2 x y 2^xy 2xy的形式,使得它们中至少有一个的y是奇数。接下来分类讨论:

  1. 当a和b都是奇数时,根据题目给出的结论,可以只存下 a n a^n an b n b^n bn最后的63个二进制位。因此用unsigned long long搞快速幂就好了;
  2. 当a和b一奇一偶时, l o w b i t ( a n − b n ) lowbit(a^n-b^n) lowbit(anbn)显然是1。

最后把 lowbit 的结果乘上 2 n x 2^{nx} 2nx就好了。

但是出乎意料的是我WA 20了。
经检查,发现我用unsigned long long(用ll表示)做的快速幂是这样打的:

inline ll pow2(ll x,int y)
{
	int s=1;//这里用了int,不炸才怪
	while(y)
	{
		if(y&1) s*=x;
		x*=x,y>>=1;
	}
	return s;
}

联赛时如果犯了这种低级错误估计又要赛季报销了。

T3

不难想到要二分答案
看到 c ∈ 0 , 1 , 2 c\in{0,1,2} c0,1,2,想到分类讨论。

先考虑最复杂的 c = 2 c=2 c=2的情况,假设现在有p次攻击,它们的攻击力为 a 1 , a 2 , ⋯   , a p a_1,a_2,\cdots,a_p a1,a2,,ap,那么经过到下一个敌人时,它们的总攻击力 ∑ i = 1 p a i ′ 2 = ∑ i = 1 p a i 2 − 2 ( ∑ i = 1 p a i ) + p − q \sum_{i=1}^p a_i'^2=\sum_{i=1}^p a_i^2 -2\left(\sum_{i=1}^p a_i\right)+p-q i=1pai2=i=1pai22(i=1pai)+pq
q表示在打完这次后伤害变成0的a的数量。

可以令 s 1 = ∑ i = 1 p a i 2 , s 2 = ∑ i = 1 p a i , s 3 = p s1=\sum_{i=1}^p a_i^2,s2=\sum_{i=1}^p a_i,s3=p s1=i=1pai2,s2=i=1pai,s3=p,这样就能存下这个值了。接着再用一个数组记录当前位置的 q q q即可。

c = 1 , c = 0 c=1,c=0 c=1,c=0的情况类似(移除最高次项就好了)。

还好,这题没有打挂,AC了。

T4

考场上没什么时间做,只拿了4分。
这是一道结论题。

结论1
在最优的划分中,某个众数只会出现至多一次,否则显然可以将相同的众数所在的集合合并来减小答案。
结论2
若将某些数字选为最后的众数,这个划分方案合法当且仅当没有选为众数的数,它们的个数的最大值小于等于选出的这些众数的个数之和。
这样一来,我们就可以得到一个 n q nq nq的做法:对于每次询问,首先找到一个最短的前缀使得a[i]的和大于等于V,其中V表示a[i]的最大值。然后从后往前把某些数字删掉:若删去数字a[i]后总和仍大于等V,那么就删掉。
结论3
所有删去的数字形成的连续段数不超过 V \sqrt{V} V

证明:
对于某个删去的数字,若它右边的数字没有被删掉,那么右边的这个数字一定大于前面的删去的数字之和,否则它就会被删去。而未被删去的数字之和大于等于V且小于2V(由值域决定),而删去的数字在其中共出现了平方次,因此删去的数字形成的连续段只有根号级别。

这样,为了优化在序列上暴力找删除的连续段,我们改为在线段树上暴力找删除的连续段:
若删去当前节点中的最小值仍不能满足条件,直接返回;若将右节点整个删去仍满足条件,那么将其删去并遍历左节点;否则遍历先右节点再遍历左节点。
总复杂度 O ( n V log ⁡ 2 n ) O(n\sqrt{V} \log_2n) O(nV log2n),实际上很难卡满,期望得分100。

总结与反思

虽然这次题目总体难度不大,我会做3道题,但是第一题思考得不完善,第二题犯了一个极其低级的错误,实在不应该!
打代码前一定要三思,打完后不要急着测样例,而是用眼睛查错。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值