思维的体操
博主现在是一位\(ACMer\)萌新,目前阶段在CF上找1800分左右的思维题做做。
在此记录一下吧。
CF1010C -1800'
由裴蜀定理可知,由这\(n\)个数能得到的余数集和他们的\(gcd\)一个数得到的余数集是相同的
CF1096D -1800'
\(f[i][j]\)表示前\(i\)个数最多拼到\(hard\)的前\(j\)位的最小代价
若\(s[i]==h[j+1]\),那么\(f[j]=min(f[i-1][j]+a[i],f[i-1][j-1])\)
要么删要么让\(hard\)中断嘛。
否则\(f[i][j]=f[i-1][j]\)
显然第一维可以滚掉。
CF1283E -1800'
贪心
最小值:把所有坐标从小到大排序,从左到右扫一遍,对于有人的坐标,如果左边一个单位没有人就左移,然后还有1个人就不动,还有2个或以上的话就右移一个
最大值:从左到右每碰到一个有人的坐标就把以这个坐标为起点的3个点合并
CF813B -1800'
暴力
把所有\(x^a+b^y\)放到一个数列里两两区间和\([L,R]\)求交集即可。
CF358D -1800'
DP
\(f[i][1]\)表示前\(i\)个先拿第\(i\)个再拿第\(i-1\)个的最大值
\(f[i][0]\)表示前\(i\)个先拿第\(i-1\)个再拿第\(i\)个的最大值
边界\(f[1][1]=0\),其它均为\(-inf\)
CF911D -1800'
对于长度为\(len\)的区间,数对个数为\(sum=len*(len-1)/2\)
设翻转后逆序对数量为\(rest\),则翻转前逆序对数量为\(sum-rest\)
两者只差也就是变化量为\(sum-rest*2\)
后者显然是偶数,于是只要判断\(sum\)的奇偶性即可判断奇偶性是否变化
CF909C -1800'
DP
\(f[i][j]\)表示前\(i\)个,第\(i\)个缩进到\(j\)的方案数
若第\(i-1\)位是\(for\)的话,那第\(i\)位必须缩进,\(f[i][j]=f[i-1][j-1]\)
若第\(i-1\)位不是\(for\)的话,\(f[i][j]=\sum_{k=j}^{n}f[i-1][k]\)
维护一下后缀和即可
CF1446B -1800'
DP
最大子序列的思路,设\(f[i][j]\)表示以\(a_i,b_j\)结尾的最大值,然后考虑继不继承前面的答案就行
CF543A -1800'
完全背包,注意模数别开\(long long\)
CF1221D -1800'
DP
首先一个很重要的结论就是每个栅栏加1的次数只能是\(0,1,2\)
于是令\(f[i][j]\)表示前\(i\)个栅栏,第\(i\)个栅栏加长\(j\)次使得没有相邻相等的情况的最小花费,然后按情况转移即可。
答案就是\(\min {f[n][0], f[n][1], f[n][2]}\)
CF1381B -1800'
观察可以发现,\(n*2\)及以后的数肯定在一段里的,然后\(n*2-1~n*2\)区间内也是在一段里的。
于是就将原数列分成了若干段,然后跑\(01\)背包看能不能拼出\(n\)就行了。
CF1509C -1800'
DP
把原数列排序,令排序后的数列为\(a\),显然最终数列前\(i\)位一定是\(a\)中连续的一段。
于是令\(f[i][j]\)表示把\(i~j\)这一段作为最终数列的答案,
则\(f[i][j]=min(f[i+1][j],f[i][j-1])+a[j]-a[i]\)
答案就是\(f[1][n]\)
CF478C -1800'
具体方案无需考虑,显然当数量最多的气球不超过其它2种颜色的时候答案就是总气球数除以\(3\),否则答案为其它2种颜色气球数的和。
CF687C -1900'
DP
令\(f[i][j]\)表示一堆为\(i\)一堆为\(j\)的情况是否存在,然后就是\(01\)背包的那一套了。
最后对每个\(i\)看\(f[i][k-i]\)是否非零即可。
CF1117C -1900'
二分答案
判断\(mid\)秒能不能行先让风刮\(mid\)秒,再看和终点的距离在不在\(mid\)以内即可。
CF1114D -1900'
DP
读入的时候把颜色相同的区间合并,然后
\(f[i][j]\)表示区间\([i,j]\)变成颜色一样的最小次数。
CF535C -1900'
二分答案
一个\(R\)是可行的当且仅当\(A+(R-1)*B<=T\)且\([L,R]\)的食物总量\(<=M*T\)
CF803C -1900'
显然\(n\)一定是最大公约数\(d\)的倍数,于是枚举\(d\),判断\(k>=d*n*(n+1)/2\)是否成立即可。
直接判断会爆long long,移项即可。
CF10C -2000'
一个关键性的结论就是\(s(x)=x\mod 9\),所以
于是用桶统计余数为\(0\to 9\)的个数,然后枚举\(A,B,C\)的余数,统计即可。
最后要减去\(A*B=C\)的情况,数论分块一下就行。
CF59E -2000'
这种有限制的最短路,而且边权为\(1\)的,用\(bfs\)就好了。
用哈希表记录三元组,最后队列里存边,最短路和前驱都用边存。
CF15C -2000'
显然每一辆车都是一个独立的\(nim\)游戏,直接求异或和就好了。
暴力求当然会\(T\),考虑到偶数和下一位的异或和肯定是\(1\),于是处理一下首尾即可。
CF1601B -1900'
设\(f[i]\)表示跳到\(i\)(也就是滑到\(i+b[i]\))处的最小步数。
定义\(l[i]\)为深度为\(i\)处能跳到的最高点,显然
然后考虑转移,
至于\(j\)怎么求,可以用树状数组维护前缀最大值
CF1601C -2300'
线段树+贪心
一个很显然的结论:\(b\)数列是按从小到大顺序插进去的。
于是直接把\(b\) sort一下放在\(a\)左边,然后考虑把\(b\)依次移到最佳位置。
由结论知最佳决策点一定是单调不减的,于是可以把\(a\)看成一个01序列。
设当前在移动\(b_j\),如果\(a_i>b_j\)那么就是\(1\),等于就是\(0\),小于就是\(-1\)(把\(b_j\)移到\(a_i\)后面对答案的贡献)。
所以对于\(b\)中每个元素,找到新序列中的最大前缀和就行了,这个东西显然可以套路地用线段树来维护,因为\(b\)递增,所以新序列每个位置至多变\(2\)次,可以通过\(O(n)\)次的单点修改来维护最大前缀和。
这题套路很具代表性,所以写的比较具体。
CF1630D -1800'
一个结论是只要区间内的数-区间外的数大于等于\(k\)就行了。
于是直接滑动窗口即可。
CF702D -1900'
很简单的数学推导题,记得特判\(d\leq k\)的情况。
CF451D -2000'
不难发现,一个子串是好的,当且仅当首尾相同,于是就简单了。
CF1311D -2000'
暴力。
枚举\(A\)从\(1\)到\(2a\)(超过\(2a\)的话完全可以把\(a\)变到1),然后在\(a\)的倍数里枚举\(B\),最后\(C\)就可以直接确定了。
时间复杂度\(O(n\log n)\)
CF1295D -1800'
仔细思考可以发现,答案就是\(\Phi(m/gcd(a,m))\)
CF1354D -1900'
看到题容易想到用multiset模拟,但multiset删值不太好删。
但发现题目只需要在最终集合随便输出个数即可,应该要想到不需要真的去维护集合。
可以直接二分答案\(x\),检验只需要把所有数分为\(\leq x\)的和\(>x\)的,然后把所有操作过一遍就行。