2022蓝桥杯省赛复盘+部分题解(C++ A组)

2022蓝桥杯省赛复盘+部分题解(C++ A组),第1张

与其说写题解,不如说是自己场上心里完全没数,下来想一遍发现T1(没加周围4刀),T2(把放满的状态当成了先手败,惯性思维了属于是),T4,T6(漏写更新条件)都挂了,心态爆炸. OI赛制恐怖如斯,估计只有60分了,连国赛都去不了了。



该好好反省下自己做题浮躁的习惯了,上次CSP就两眼出思路的T4也是卡了两小时,导致没时间做T3。


更远的追溯到南京,2h12min第一发交H的树形dp,思路没错,因为写错变量名卡到4h24min(就是这么离谱),下来看了看1h内解决掉I,也算痛失银牌。




虽说acm不像OI,但也要少吃罚时少卡题。


另外第一次学对拍,附上对拍代码:

int main(){
    while(1){
        system("gen.exe > in.txt");
        system("E.exe < in.txt > out1.txt ");
        system("baoli.exe < in.txt > out2.txt ");   //baoli中间不能有空格,不然命令行识别不了
        if(system("fc out1.txt out2.txt")) break;
    }
}

A

法一:dp,记dp(r,c)表示切割一块r行c列的最少次数(没算外围的四刀),转移方程:

dp(r,c)=min(1+dp(r-i,c)+dp(i,c)), 1<=i<=r-1;

dp(r,c)=min(1+dp(r,c-j)+dp(r,j)), 1<=j<=c-1;

最后答案:dp(20,22)+4;
法二:考虑每条要切割的边(如图中红线,长度为1),如果一次只能切割一条边,答案就是边数=21 * 20+19 * 22;
不过显然可以一次切多条边。


考虑每个交点对节省切割次数的贡献,对于每个交点,最优的方法是要么横着,要么竖着切,只能选一种,1次切了2条,使次数-1。


那么答案 - = 交点数 (19 * 21) 。



B
博弈论+状压dp.
用8位2进制数记录8个格子的状态,每位上为1代表对应方格被选,0代表没被选。


dp[i]=1时代表i为先手必胜态。



博弈论基础可知,先手必败态可转移到若干先手必胜态,而转移过后的状态标号一定小于原标号,故倒序做一遍即可。



Code:

#include
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define IOS {cin.tie(0); cout.tie(0); ios::sync_with_stdio(0);}
#define ll long long
#define P pair<int,int>
int t[]={1,2,4,8,16,32,64,128,3,6,12,48,96,192};
int dp[256];//当前情况下先手是否必胜
int main(){
    dp[255]=1;  //场上读假题了,惯性思维以为谁放不了谁输..
    per(i,255,0){
        if(!dp[i]){
            rep(j,0,13){
                if((i|t[j])==i )dp[i^t[j]]=1;
            }
        }
    }
    cout<<dp[1]<<dp[3]<<dp[2]<<dp[6]; //实际上此时小蓝是后手
}

C
全场最简单的送分题感觉。



记sum为n个数之和。


对于特定i, ∑ j = 1 n a i ∗ a j \sum_{j=1}^na_i*a_j j=1naiaj = a i a_i ai * (sum- a i a_i ai);
考虑每对积算两次,则2 * ans= ∑ i = 1 n a i \sum_{i=1}^na_i i=1nai*(sum- a i a_i ai).
或者想不到算两次的话,遍历的过程中维护sum即可。


D
从D题开始怎么难度就上来了啊。








(第一次参赛,天真的我还以为真的是暴力杯,题目会很水(bushi))
题面:

大致想法是对 a l a_l al^ a r a_r ar=x 的一对(l,r)更新区间,即左端点位于[1,l],右端点位于[r,n]的询问是yes,比较常见的离线套路。



做法:离线询问,并按右端点从左到右对询问排序。


从左向右遍历,遍历到i时,将i视为 a l a_l al^ a r a_r ar=x 的(l,r)中的r。


对于前面所有的 a l a_l al^x= a r a_r ar,只考虑最靠右的 a l a_l al即可,这个由于数据范围小可以用一个数组实现。



那么右端点>=i的所有询问,如果左端点<=l即为yes。


由于询问是按右端点排序的,统计询问答案也是随着遍历有序的。


E
期望dp+逆元
d p i dp_ i dpi为爬到高度i时的期望时间,直接上式子:
d p i − 1 dp_ {i-1} dpi1=(1- p i p_i pi)* d p i dp_i dpi + p i p_i pi * d p 0 dp_0 dp0 + 1;
显然 d p n dp_n dpn=0,那么我们可以得到n个关于 d p 0 dp_0 dp0 d p n − 1 dp_{n-1} dpn1的式子,解出 d p 0 dp_0 dp0即可。



发现 d p n − 1 dp_ {n-1} dpn1式子右边只与 d p 0 dp_ 0 dp0有关,把 d p n − 1 dp_ {n-1} dpn1带入 d p n − 2 dp_ {n-2} dpn2,再把 d p n − 2 dp_ {n-2} dpn2带入 d p n − 3 dp_ {n-3} dpn3 … 每一项都是 d p i dp_ i dpi= 系数* d p 0 dp_ 0 dp0+ 常数。


最终 d p 0 dp_ 0 dp0=系数* d p 0 dp_ 0 dp0+ 常数。


F

首先,要求的是最低跳跃能力,一眼二分。



然后注意到,从左向右和从右向左跳是等效的。


于是转化为从0跳到n,可跳>=2*x 次。



又想到,对于当前所在的点和给定的跳跃能力,贪心地尽可能跳到最右的一定最优。



做法:check(跳跃能力k)即可:
d p i dp_i dpi 为从i往后跳能上岸的最多次数。


首先 d p i dp_i dpi<= H i H_i Hi; 然后 d p i dp_i dpi 先找最右边能到的 d p i + k dp_{i+k} dpi+k, 如果 d p i + k dp_{i+k} dpi+k不能满足则把 d p i + k dp_{i+k} dpi+k 的次数全给 d p i dp_i dpi,再往左找下一个[i,i+k]范围内最大的。


最终判断 d p 0 dp_0 dp0>=2 * x;
d p i dp_i dpi加的同时,记得 d p i + k dp_{i+k} dpi+k要减。


找最右边能跳到的石头可以用set维护。


check的总复杂度O(nlogn).

G
只打了n方log的暴力,先咕

H
比较偏爱的计算几何,想出来极角排序+主席树的做法,可惜没时间打,只打了极角排序+n方的暴力,咕。


I
暂时只会暴力,咕。


J
听说原题一眼题,可我只会暴力555,咕。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/584928.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存