思维题集合

1. cf Binary Strings are Fun

emmm,刚开始的做法T了,看了题解发现有点小结论,希望再看到的时候加油吧。

2. loj 越狱

怎么判断是否发生越狱情况?我们可以这么想。结果\(ans=总情况-不越狱情况\)
那么总情况很好算,\(Q_全=m^n\)
不越狱情况,对于第一人有m种情况,而第二人开始,每人都只有m-1种情况,故\(Q_不=m*(m-1)^{n-1}\)
结果\(ans=Q_全-Q_不\)

3. cf Elemental Decompress

模拟题目所给的过程,注意所用的方法即可,不是特别难

4. cf Gardener and the Capybaras (hard version)

注意审题——"The string consists of English letters 'a' and 'b' only."

5. cf Winner

简单题,就是个思维题,注意实现方法就行了,没头绪话的看看自己的提交过程
自己的代码提交了四次,下面记录错误点
第一发:审题不清!!!当有多个最大时,我们需要找这多个最大代表的人中,在题目所给的顺序中,第一个不小于最终结果的人
第二发:依旧是审题不清!如上所述,我的代码判断的是这些人最终时的顺序,而不是首次超过时的顺序
第三发:在我的第二遍遍历过程中,我重置了p所指向的位置,但这时候需要注意,a数组经过排序后,原来的p会影响我想要的结果,所以将后面的下标改为新的q,就不会出问题了
继续努力哈!

6. abc 299 D Find by Query

交互题,让你通过询问找到s中0与1的任何一个分界点
利用二分求解,\(q(mid)==0\)向右查,\(q(mid)==1\)向左即可,目标就是找到0与1的分界处,而且因为题目中,\(a[1]=0,a[n]=1且n<=200000而2^{15}=32768\),所以二分一定能找到,且能满足20次的询问条件。
详见代码

7. cf Making Anti-Palindromes

详见官方题解,有个小结论

8. cf Mingming's Grid Paper 2

题面:image
规律题,结论:\(ans=2^n+2^m-2\)

9. abc 300 D AABCC

思维题
先通过欧拉筛找出所有的质数,通过题目的范围可以找到质数的最大范围
在从前往后遍历质数,注意三个数互异,所以前面小的不成立的话,后面大的也一定不成立
记得剪枝,值得做

10. Codeforces Round 872 (Div. 2)

这一场可以做一下,比较有意思

11. abc 312 E - Tangency of Cuboids

题意
三维平面内给定 n 个长方体,保证这 n 个长方体两两不相交。问你对于每个立方体,与其任意一面有接触的立方体共有几个?
思路
官方题解思路,我们考虑长度为 1 的立方体,对其打上类的标记。之后我们考虑一件事情,就是面面接触的大长方体其实可以看作至少存在两个长度为 1 的不同类的立方体相交。那么我们可以以小立方体为中心,题目数据 \(x, y, z <= 100\),故我们可以考虑每一个小立方体的面面相交情况,因为好判断,若存在不同类相交,那么就在 ans 该类中放入对应类的下标。因为每个面接触的小立方体不一定就是一个,所以 ans 类里面还得去重。最后每一类里面放的个数即为答案。
详见代码,上述解释不完全
代码
\(O(m^3 log n)\) 法:qiansui_code

12. cf 893 div2 B. The Walkway

纯纯思维题,有空可以再试试
赛时模拟代码:传送门

13. 比较像的两道给定区间信息的思维题

14. cf 907 div.2 C. Smilo and Monsters

考虑所有 \(a_i\) 的和为 sum,那么我们最多利用 sum / 2 次操作 1 来尽可能利用操作 2 消灭大数
Qiansui_code

15. cf 899 div.2 C. Card Game // Qiansui_code

对于每一个位置后面的大于 0 的值,均有办法取得
先将位置 i 后面的奇数位置上的正整数全部取完,取之后有变动也一直取,仅剩下偶数位置上的正数
再将当前位置 i 取走或移除,那么后面所有的偶数位上的正数会变到奇数位,再进行上面的操作即可

16. cf 155 div.2 B. Chips on the Board // Qiansui_code

对于每一行考虑,要么当前行有,要么所有列均有。故对所有行考虑,要么所有行均有,要么所有列均有,取最小即可

17. cf 154 div.2 C. Queries for the Array // Qiansui_code

利用 now 记录当前元素个数,利用 sorted 标记前 sorted 个数已知升序,利用 not_sorted 标记前 not_sorted 已知无序
当进行操作时:

  • 操作 +:不影响有序和无序的个数
  • 操作 -:对于 \(sorted\),当 \(now > 0\) 时,\(sorted = min(sorted, now)\);对于 not_sorted,当出现 now < not_sorted 时,无序状态被破坏,设置 not_sorted = inf
  • 操作 '1':如果说 $now \ge not \underline{}sorted $,说明无序后面说有序,矛盾
  • 操作 '0':如果说 \(now \le sorted\),说明有序里面说无序,矛盾

18. cf 897 div.2 E2. Salyg1n and Array (hard version) // Qiansui_code

注意!n 和 k 都是偶数!
前面每 k 段单独询问,总共不超过 50 段
末尾若存在不足长为 k 的一段,我们注意到并且利用题目中存在的旋转操作得到解。
在末尾长为 len = n % k 之前再取一段 k,询问 l = n - n % k + 1, l + len / 2, l + len 即可。具体解释见下图:
image

19. cf 908 div.2 E. Freedom of Choice // Qiansui_code

这一场的题目都是思维题,没啥算法要用到,贪心就行
这题先考虑 \(m = 1\) 的时候,此时我们可以发现一件事情:如果 $ r - l > n $,那么最终的多重集的大小一定可以是 [l, r] 之间的一个数,且这个数没有在给定的多重集中出现过;如果 $ r - l \le n $,那么由于题目给定 \(\sum n \le 10^5\),所以可以枚举 [l, r] 中的每一个数,判断最终多重集的大小为其时包含其数字的最少个数
那么对于 $ m > 1 $ 也是同理操作即可,那么由于有多个多重集,我们在枚举最终多重集的大小之前,可以维护出给定的 m 个多重集中数字的种类和个数以及组的位置,对于每一个组都有 \([l_i, r_i]\) 的必选限制,对于每一个组都遵循 “尽可能的选别的数,不足再用枚举的大小的数字填充”。
详见代码

20. cf 158 edu D. Yet Another Monster Fight // Qiansui_code

对于每一个位置,首先当前位的怪物要杀死,其次,左边所有怪的最坏情况得满足,右边所有怪物的最大情况也得满足,因为题目的攻击的随机进行的。所以我们需要维护前缀最大和后缀最大,再遍历一遍取最大的最小即可。

21. cf edu 155 D. Sum of XOR Functions

Qiansui_code

考虑拆位,对于每一个位分别统计其对答案的贡献。

显然,只有连续区间内出现奇数个1才会对答案产生贡献。
我们考虑拆位之后每一位从前往后构成的01串:

  • 如果说区间[1, r]有奇数个1,区间[1, l]有偶数个1,则区间[l, r]有奇数个1
  • 如果说区间[1, r]有偶数个1,区间[1, l]有奇数个1,则区间[l, r]有奇数个1

由此,可以从前往后维护前缀中1的个数即可

\(cnt[0/1]\) 表示前缀中含有多少个偶数/奇数个1
\(sum[0/1]\) 表示含有偶数/奇数个1的区间的总长度
\(len[0/1]\) 表示以i结尾的含有奇数个1的区间的总长度
则:
$ len_i = i \times cnt_{1 - i} - sum_{1 - i} $

显然这一位总的合法的长度为 $ res_i = \sum len $,而 \(ans = \sum res_i \times 2^i\)

22. 2018 ICPC 青岛站 ZOJ 4060 Flippy Sequence

题意:
给两个长度不超过1e6的等长的01串S和T,可以选择S的至多两个区间,进行翻转,要求翻转后等于T,求方案数?

思路:
考虑在哪些区间里面,两个字符串是不同的,如果不同的个数超过了2,那么一定无解

  • 如果不同的区间个数为 0,即两个字符串相等,此时两次操作需要选择同一区间,共有 $n + n - 1 + n - 2 + \cdots + 2 + 1 = \frac{n \times (n + 1)}{2} $ 种选择方式
  • 如果不同的区间个数为 1,此时这一整个区间必定都需要进行一次操作。有两种情况,第一种是两次操作均处理这个不同的区间,假设这个区间的长度为 \(len_0\),方案数为 \((len_0 - 1) \times 2\);第二种是考虑旁边的相同区间,两次操作均覆盖一侧的相同区间,只要其中的一次同时覆盖当前的不同区间即可,假设旁边的相同区间长度为 \(len_1\),此时方案数为 \((len_1 - 1) \times 2\)。此情况最终的方案数之和为 $(n - 1) \times 2 $
  • 如果不同的区间个数为2,此时仅有六种情况。设区间情况为 101,1表示不同区间。则两次操作可以选择:左1 + 右1、左10 + 右01、全101 + 中0,一共三种选择,操作的顺序可以交换,所以一共有六种选择

Qiansui_code

23. cf edu 159 D. Robot Queries

题解传送门
上面这篇题解写的很详细了,过程非常完整,这里仅记最后的结论

  • 如果询问点 s {x, y} 出现在区间 \([0, l - 1]\) 或 $ [r + 1, n] $ 的路径上,则一定成立
  • 如果询问点 s {x, y} 出现在区间 $ [l, r] $ 中,且变换后的点 s' \(\{f[r].x + f[l - 1].x - x, f[r].y + f[l - 1].y - y\}\) 出现在区间 \([l - 1, r - 1]\) 的路径上,则一定成立
  • 反之,不成立

Qiansui_code

24. cf 930 div.2 B. Binary Path

思考模拟走的过程

  • 如果在最后一列,只能向下走;
  • 如果在第二行,只能向右走;
  • 在第一行时,如果下面的字符小于右边的字符,必定向下走;
  • 在第一行时,如果下面的字符等于右边的字符,向下向右都可以;
  • 在第一行时,如果下面的字符大于右边的字符,必定向右走,此时前面的走法将被重置。

如此,即可得:

int ans = 1, pos = -1;
for(int i = 1; i < n; ++ i){
	if(ss[0][i] == ss[1][i - 1]) ++ ans;
	else if(ss[0][i] < ss[1][i - 1]) ans = 1;
	else{
		pos = i; break;
	}
}

Qiansui_code

25. cf 927 div.3 C. LR-remainders

正序按照给定的操作走,会发现难以计算最后的取余值,所以考虑倒序操作
先走一遍操作找到最后留下的那一个值,再从这个值出发,逆序遍历给定操作集,逆序记录取余值即可

Qiansui_code

26. cf 927 div.3 E. Final Countdown

数字很大,显然不能直接计算
观察可知,$ ans = \displaystyle \sum_{i = 0}^{n - 1} (int)[s_0...s_i]$
考虑每一位数字对答案的贡献,可以得到 $ ans = \displaystyle \sum_{i = 0}^{n - 1} s_i \times \sum_{j = 0}^{n - 1 - i} 10 ^ j $,转换一下式子,可以得到 $ ans = \displaystyle \sum_{i = 0}^{n - 1} 10 ^ i \times \sum_{j = 0}^{n - 1 - i} s_j$

所以,我们可以先预处理出给定数字字符串的数位前缀和,再从后往前遍历,同时统计一个进位值,每遍历一位即确定最终答案的一位数值,从小到大确定

Qiansui_code

27. abc 329 E - Stamp

题解传送门
可以知道的是,最后的一次覆盖肯定是完整的,那么其覆盖的位置的字符串相当于可以全部置空,以方便匹配其之前的覆盖,而其所能影响的范围只有前后 2m 个长度的字符串,所以我们仅需要对这 2m 长度的字符串考虑即可
如此,总时间复杂度为 \(O(nm^2)\)
Qiansui_code

28. cf 837 div.2 B. Hossam and Friends

思路
对于每一对不相识的朋友,id 小的记下其所有不相识朋友的 id - 1 的最小值,在不考虑别的人的情况下,这是 id 的人向右最长的好区间
但是右边的人也会影响前面人的选择,所以可以取自己以及右边所有人的标记的最小值,这是在满足题意的情况下,可以向右取得的最长好区间
对每一个人都这么考虑,累加答案即可

Qiansui_code

posted on 2023-03-22 23:02  Qiansui  阅读(40)  评论(0编辑  收藏  举报