Edu Round 170 Review

Edu Round 170 Review

A

分析

一个很显然的根据前缀划分的贪心,直接指针模拟就好了。

Code

#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string a,b;
cin>>a>>b;
int l1=a.length(),l2=b.length();
int p=0;
while(p<l1&&p<l2&&a[p]==b[p])p++;
if(p>0)p--;
cout<<l1+l2-p<<'\n';
}
}

B

分析

打表就发现需要输出的就是 2n ,然而这道题我卡了十多分钟,实在是有点sb了。

具体证明的话可以用数学归纳法,也可以直接证明,都是比较容易的。

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7;
inline int power(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)ans=ans*a%MOD;
a=a*a%MOD;
b>>=1;
}
return ans%MOD;
}
const int N=2e5+1;
int t,n[N],k[N];
inline void solve()
{
cin>>t;
for(int i=1;i<=t;++i)scanf("%d",&n[i]);
for(int i=1;i<=t;++i)scanf("%d",&k[i]),printf("%lld\n",power(2,k[i]));
}
signed main()
{
solve();
}

C

分析

其实思路上面很简单,只需要以每个数为开头贪心地连续去选择尽可能多的数字就可以了。

注意这样做是 O(n2) 的,那么考虑如何在枚举的时候快速地从现在的答案推知下一个答案。

很容易想到一个简化的莫队,从 [l,r][l+1,r+1] ,实际上只是增加了一个数,去除了一个数而已,通过增量就可以计算出来。

边界写错了吃了两发罚时(实际上可以不需要去重的,所以说本人的找屎能力真的强)。

又成功地在模拟题上面写出了一道屎山代码。。。

Code

D

分析

因为实现能力太差,C做了一个小时,导致D只有不到二十分钟的时间了,大概扫过去想了一个很骚的做法,就是倒叙枚举然后贪心地选择贡献即可,结果发现题看错了。。。

这种涉及到抉择的题发现贪心是假的,那肯定就是DP了。

那其实阶段和状态也很容易设计出来。

定义 dp[i][j] 为前 i 个数字 选择了 j 点智力加点能够获得的分数(注意此时体力的加点一定是唯一确定的,因此我们没有必要单独开一维来单独记录,前提是我们需要统计出来一个数组来记录任意某个位置 pos 之前一共出现了多少个 0 ) 。

那么转移方程也非常的水到渠成:

如果 ai=0 ,那么所有的 dp[i][j]=max(dp[i1][j],dp[i1][j1])

如果 ai>0 ,那么所有的 dp[i][j](jai)=dp[i1][j]+1

如果 ai<0 ,那么所有的 dp[i][j](jsum0(ai))=dp[i1][j]+1

注意到我们会多次执行区间加的操作,实际上你可以写一个线段树,或者是树状数组,然而都太麻烦或者不好实现(对我来说)。

我们可以直接采用差分数组,但是缺陷就在于,虽然可以多次进行区间加法,但是一只能统计一次。观察到这道题 m 的数据范围非常小,所以每次遇到一个 0 之前,我们就暴力地统计一遍差分数组,然后加到 dp 数组里面,而后进行 0 处该进行的转移,再把差分数组清零,重新进行后续的区间加操作即可。

Code

E

非常好的一道计数题,让我“温习“了一下在高二的时候学习过的卡特兰数。

前置知识

卡特兰数

定义背景

由于这一类组合数对于实际问题有意义,所以才会被单独讨论,它适用于如下情况:

  1. n 个人排成一行进入剧场。入场费 5 元。其中只有个 n 人有一张 5 元钞票,另外人 n 只有 10 元钞票,剧院无其它钞票,问有多少种方法使得只要有 10 元的人买票,售票处就有 5 元的钞票找零?
  2. 有一个大小为 n×n 的方格图开始每次都只能向右或者向上走一单位,不走到对角线上方(但可以触碰)的情况下到达右上角有多少可能的路径?
  3. 在圆上选择 2n 个点,将这些点成对连接起来使得所得到的条 n 线段不相交的方法数?
  4. 对角线不相交的情况下,将一个凸多边形区域分成三角形区域的方法数?
  5. 一个栈(无穷大)的进栈序列为 1n 有多少个不同的出栈序列?
  6. n 个结点可构造多少个不同的二叉树?
  7. n+1 组成的序列,满足任意前缀和非负,有多少种构造方案?

公式

  1. Hn=C2nnn+1

  2. Hn=C2nnC2nn1

  3. Hn=Hn1×4n2n+1

  4. DP的方式求(卡特兰数实际上是一个匹配的过程)

    定义 fi,j 为,前 i 个数,剩下了 j 个没有匹配的方案数,那么最后的答案就是 f2n,0

    转移方程也很好写,

    fi,j+=fi1,j1 当前作为左括号。

    fi,j+=fi1,j+1 当前作为右括号并和一个左括号匹配。

分析

我们钦定两个人分别为 A,B ,明显的是这道题中 1 是一个比较特殊的花色,对于其他普通的花色,我可以两个人选的一样,然后两个人内部进行分配使得 A 总是赢;也可以暂时让 B 的牌多于 A ,后面拿若干张的 1 来进行弥补性配对。

我们考虑如何进行这个计数DP。

对于 1 花色特殊考虑,我们先不处理它。

对于其他任意一种颜色,我们应用第一种分配策略时,把 m 张牌均分给两个人,首先假定这个 1m 的序列已经降序排列好了。

那么我们从大到小以此给两人分配,发现如果任何时刻,我给 B 分配的牌都必须要小于等于给 A 分配的牌,才能够满足题设条件。

那么这实际上就是一个卡特兰数 Hm2,可以比较性地发现。

我们应用第二种分配时,很容易想到先选出 k (偶数)个来不进行配对之后和 1 配,然后剩下的 mk 个按照卡特兰数配对。

看起来没什么问题,实际上也确实没问题,但在这道题的计数规则下就是错误的,由于我选出来不配对的几个数实际上是归于 A 的,这就意味着分别属于 A 的参与匹配的集合A的暂时不参与匹配集合 的两个数,可能会被重复计算。

反观我们用 DP 求卡特兰数的过程,实际上就已经把这里我们需要的答案给计算出来了,我们想要剔除 k 个,然后剩下的配对,那么方案数就是上面提到的 fi,k ,那么我们转移起来也就相对来说很好想了。

dpi,j 的定义是 前 i 个花色 (不包括 1 ),一共剩下了 j 个的方案数。

好久没有写过题解了。。。。

posted @   Hanggoash  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
动态线条
动态线条end
点击右上角即可分享
微信分享提示