2024牛客暑期训练营第一场补题(超详细)

补题报告- 第一场

解决题目C,H,A,I,B,D

解题思路

C:Accept

用一个变量sum记录总和,会发现对于序列中a[i]的值,再经过s1,s2……sn加和时,

它所具有的权值为a[i]*i;

所以在进行t次删除尾节点时,对sum进行减去a[i]*i也就是减去a[i]权值的操作。

在进行添加尾节点的时候,进行sum+=新增节点权值的操作,便可以维护最终答案sum

H:Accept

题意是有n个队伍要参加两场比赛,但是一个队伍只能参加一场比赛,也就是说,

如果这个队伍出现在两个比赛的可参加名单里,就可以随意安排这只队伍参加两场中的

一场比赛。

题目给出的队伍参加队伍的状态,也就是解题数和罚时,权值解题数>罚时

让我们输出主角队能获得的最好名次。

很明显,我们需要记录主角队的两次比赛不同的状态,计算它在对应比赛所能取得的最好名次,在一场比赛中,主角靠自身能力到达x名次,为了让主角取得更好的名次,我们会希望,

比主角排名靠前的队伍不要参加本场比赛,也就是让那些能参加两场比赛的队伍去参加另一场比赛,遍历前1~x名,如果发现该队伍名字出现两次,那么让主角排名靠前,也就是x--。

输出两场比赛主角队所能取得的最好排名为止。

A:
赛时:

题意是对于所有的长度为n的序列,且每个元素都是非负整数并且小于2^m,问这些序列中,存在至少一个子序列的按位与和为1的序列有多少个。

对于这一题首先打了个表,摸清了一下大体规律。

我的思路是

先构造1~n按位与和为1的序列,那么剩下的元素便可以任意搭配。

对于长度为k合法序列来说,除了2^0位必须是1,其他位必须不能全是1

也就是说,对于2^1~2^m-1这些位数的情况共有Ck 0+Ck 1+…Ck k-1种情况,也就是

2^k-1种情况,将2^1~2^m-1这些位数的情况数相乘便是长度为k的合法序列情况数

对于长度为n的合法序列,只要其中存在长度为1~n的合法序列之一即可,并与剩下元素的情况数 spid(spid(2,m,q),n-i,q))相乘即可,但是我的解法只有二十多分,我觉得应该是在对

这k个数与剩下元素之间的排序存在问题。

补题:Accept

补题时咨询了学长学姐,发现我的方法存在重复计算的地方

补题思路1:

--对于长度为i的合法序列,需要为它提供i个位置,需要用到组合数,也就是C(n,i)

--对于长度为i的合法序列,可以发现,如果再继续搭配2^0位为1的数字,也就是奇数,会组成长度为i+1的合法序列,所以其他剩余数字的选择不能是奇数,也就是情况数不能包含2^0位。

--所以我的做法就是计算出长度为i的合法序列的情况数,也就是

ll t=1;

        ll x=spid(2,i,q);///每一位不能同时为1

        ///那么数量就是2^i-1

        if(x==0)x=q-1;

        else x--;///减一操作

        x=spid (x,m-1,q);///总共还剩m-1位

        t=t*x%q;///当前长度为i的合法序列情况数

然后将剩余的偶数情况数乘上去

              t=t*spid(p,n-i,q)%q;再乘上组合数即可。但很明显,不能很好的解决问题。

补题思路2:

       用扩展欧几里得(题目给的模数不一定是质数)算出C(n,i)的组合数时发现,到一定大小后,求出来的组合数都是0(为此我换了很多欧几里得板子),后面经指点发现这实际上是逆元不存在的情况,因为c(n,i)=c[n]/(c[i]*c[n-i])。

补题思路3:

      求逆元的方式无法解决组合数问题,其实组合数的球法不唯独求逆元,用杨辉三角公式推也是可以的。

              C(n,m)=c(n-1,m-1)+c(n-1,m)

有两种形式,一种是dfs求单个组合数,也有直接打表的n^2复杂度放数组里,我选择了第二种:

C[0][0]=1;

    for(int i=1; i<=n; i++)

    {

        for(int j=0; j<=i; j++)

        {

            if(!j)C[i][j]=1;

            else C[i][j]=(C[i-1][j-1]+C[i-1][j])%q;

        }

}

‘构造完后c[n][i]便是所要求的组合数,再把原来的答案进行修正,

t=t*spid(p,n-i,q)%q*C[n][i]%q;

    ans=(ans+t)%q;

最后输出ans,便可以accept该问题。

I:预处理,时间复杂度n*m*4 赛后 Accept

因为光路可逆,所以在光路图中只能存在链或者环,题解说只要把他们分别抽

出来就可以。但很明显难点就是在于怎么抽取这些奇怪的东东

补题思路1:

对于链,很明显是贯穿于我们的网格图的,所以我们可以采用从外射入的方式反向找到我们想要找到的链。

补题思路2:根据补题思路1,我们就可以找到所有的链,那么剩下的便是环

解题思路:

我们肯定需要建立一个数组ans[2000][2000][4],最后一个维度代表的是方向

对于链:

根据补题思路1,由于是一条链,那么必然没有其他分支,因为光路可逆。所以可以用dfs跑(也可以认为是bfs,毕竟就一条线),我们可以从一头跑到另一头不重复。

所以我们需要写一个专门针对链的solve1函数,为了记录路径,还需在全局开个vector<tuple<ll,ll,ll>>vec记录路径,tuple用法和pair差不多,相当于结构体。

对于每一个边界点,从头跑到尾写一个dfs函数,退出条件显然是越界,并把到达的点放进vec里。

这时候将vec倒置,因为方向原本是-> -> -> ->,为了方便for(auto )遍历,所以倒置

这时候额外开一个存坐标的set,遍历vec时如果遇到镜子,便放进set里(函数:istan)

然后让当前点ansp[a][b][c]=st.size();

对于环:

根据补题思路2,可以知道剩下的点必然成环,那么用记忆化搜索的方式跑一下所有点即可

比如对一个点进行某个方向的dfs,最后必然回到这个点。这时候你路径上的每个点,也一样是vec中的元素,都应该等于这条环路径上的所有镜子,也就是st.size();为了防止重复跑,所以可以开一个vis[2000][2000][4]来记录当前这个点是否已经跑过。也就是说,环路径bfs的退出条件是vis[x][y][dir]==1。

这时候ans数组就已经构造好了,根据题目输入的信息,O(1)时间复杂度查询答案即可。

B:

题意:在A的基础上删去只有一个合法子序列的序列。

解题思路:对于只有一个合法子序列的序列,我们可以发现,合法子序列全由奇数构成,那只有一个合法子序列的序列的特点是,我们不可以将这个合法子序列的任意一个奇数删去,并且还能得到一个合法子序列。那么枚举这种合法子序列的情况即可。

解题步骤1:由于数字较大,所以我们可以预处理出2的几次方的数组(虽然后期实测不弄这个也能过,但确实写起来方便点了)。

根据解题思路,会发现我需要计算这种特殊的奇数子序列,这种特殊的奇数子序列的特点是,每个奇数在2^1~m-1次方位上至少得有一个特殊0.特殊0就是在这长度为i的奇数子序列中,对于2^t(1<=t<=m-1)上存在一个唯一的0,其他数的2^t位都是1。这样就能保证这个奇数如果被删除,会导致2^t&出来会得到1,从而整体得不到数字1。

这里便需要应用到球盒问题,和第二类斯大林数类似。

球盒问题:我们设dp数组,dp[i][j]表示i个数,对于j个特殊位(即特殊0)的方案数,很明显会发现dp[i][j]可以由i*dp[i-1][j-1]得到(新来的数占据了一个新的特殊位),也可以由i*dp[i][j-1]得到(给i个数再分配一个特殊位)。从而得到递推式dp[i][j]=i*(dp[i-1][j-1]+dp[i][j-1])。

解题步骤2:同样枚举合法奇数子序列的数量2~n。

根据A题,我们可以计算出其余偶数的情况数= pow2[(n - i)*(m - 1)]%q*C[n][i]%q;

如果这i个数每个数都应该由1个以上的特殊位,那么我们必须从dp[i][i]开始枚举起, 到dp[i][m-1]。同时还需要找出这j的特殊位是哪几位的方案数,也就是C[m-1][t]。

特殊位的方案数查找完毕后,还剩下不包含特殊0的位,他们的情况数几乎是可以任意放,也就是pow2[i],但是不能存在全是1的情况,也不能存在只有一个特殊0的情况(会和枚举特殊0的方案数查重),所以需要减去1和i。我们设这个数位tmp2,剩下多少个位,就需要乘上tmp2的几次方。

整理一下,会得到这个式子:

用第A题的答案去掉长度为1的答案-这里算出来的答案并取模就能得到最终答案。

D:(树状数组)

小知识:遇到不认识的模数,需要判断是不是质数(是否可以用逆元求解,否则尝试因子拆分,找出其特别性(例如,是k^w)。就比如A题在写的时候一开始尝试用逆元进行求解,还根据模数不一定是质数,特地使用的扩展欧几里得算法求逆元,但得到的结果确实几发wa,原因就是不是所有数对某个模数,都是拥有属于自己的逆元的(扩展欧几里得算法中有提及如果不存在逆元,返回值是什么)。

解题入手:对于这个特殊的模数,我们通过莫名其妙的方法,发现它是2^21 ,也就是说,对于后缀和2^21后面的部分不用考虑,又因为每插入一个数,会改变所有的所有后缀和。因为我们可以尝试维护前缀和,如何维护呢,会发现题目所给的是求所有后缀和的疑惑和,并且还给了2^21这么个特别的数字,所以我们可以维护单独所有后缀和的每一个位数的。可以用树状数组或者线段树实现(很明显树状数组更适合这份工作,因为只涉及到了累加)。最后得到的答案明显也可以按位查询实现21位,从而得到你要的sum。复杂的点在于前缀和的二进制怎么转化成后缀和的二进制。就好了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值