Loading

20230306线性代数日志

线性代数 2023-03-06

有巧妙的思维

有小技巧

【NOI2020】美食家 P6772

先考虑暴力的动态规划方法,设 dp[i][v] 表示在第 i 天并且在 j 这个节点上最大能得到的“愉悦值”。朴素地转移有 dp[i][uedge]=dp[iwedge][vedge]+c[uedge] 在有 (uedge,vedge,wedge)这条边的情况下,同时对应的第 i 天如果有美食节,判断一下所在的位置有没有举办。答案是 dp[T][1]

由于 T 过大,很明显不能这样直接做。对于这种状态转移较为多且状态个数较少(只有 n 个状态)的时候,考虑矩阵乘法。

  • 广义矩阵乘法:

  • C[i][j]=maxk=1n(A[i][k]+B[k][j])

要解决的问题是这个转移式第一维并不是每次增加1而是需要调回之前的状态,注意到 wi5 奇小,可以把一个点拆成5个点,理解成延时的效果,每个点分别表示需要延时多少单位时间。或者可以偷点懒不想这么多,直接做一个 5×n 的矩阵也可以。

还差一个转移过程,即 k 个美食节。由于 k 的大写不是与 T 同一个量级,考虑单独计算。首先将其排序,之后每次倍增跳到一个需要处理的 k 暴力将对应的状态加上值即可。

总结:简单dp+矩阵乘法优化+倍增

BZOJ3583

不难发现,将 I 置换一下,然后与 O 相乘(矩乘,顺序是 O×I),我们就得到了第一次 ij 的方案数。(根据定义就可以看出来)

考虑 uv 在恰好 d 条路径的方案数量,那么就是 (OI)d 问题在于 OI 这个矩阵是 n2 级别的矩阵,直接跑会炸掉

优化(OI)d=O×(IO)d1×I 因为 IO 矩阵是 k2 级别的,可以通过。

接下来考虑 d 条路径以内的方法。那么就是求之前所有的和,即 (OI)d[u][v] 。这里用等比矩阵求和即可(用递归或者倍增都可)

LOJ6537

先把编号都-1,因为要用到取模

同样从普通动态规划入手,设 dp[i][j] 表示剩下 i 个人,第 j 个人报 k,编号为0的人存活概率。有 dp[1][0]=1

可以找到转移式 dp[i][j]=12dp[i][(j+k)modi]+[j0]×12dp[i1][(j+k1)mod(i1)]

意义是 j 是否会 G,当然我们高贵的 0 不能 G。

动态规划不能直接转移,因为会调用还没有处理好的项。这恰好是一个方程的形式,即 dp(j)=12dp((j+k)modi)+[j0]×12K

其中 k,i,K 都是已知量。

直接高斯消元解是会炸的,这里用到一个主元法,我们发现 dp((j+k)modi)=2×dp(j)[j0]×K 也就是说最后可以把 dp(j) 有引回自己,并且成立一个一元一次方程。从而顺利解出 dp(j)

细节方面注意 [j0]

CF963E

从动态规划入手,考虑 dp[i][j] 表示这个点的期望步数。很容易列出转移式 dp[i][j]=1+dp[Δx][Δy]×pk

对于在圆外的点有 dp[i][j]=0

与上一题相同,本式子不能直接转移,我们考虑列出方程的形式。由于 R2 个未知数会炸掉,用圆最上面(对于每个 x 在圆内 y 最大的点)作为主元。方程用每个 x 最小 y 的点的下面一个点(这里的 dp[x][y]=0 即可解方程,答案即 dp[0][0]

实现方面对于每个点记录一个数组表示每个元对应的系数,注意不要忘记常数项

Odd subrectangles

首先相加的和等于计数 异或和=1

假设固定选一些列,那么每次选一行就相当于把结果异或上这些列这一行的异或和。

也就是说这么多列完全可以化为一列(通过异或和)来统计答案即可。

最直观的看法就是假如有 x 个位置是 1,y 个位置是0,那么答案就是 2y×(Cx1+Cx3+) 但是这个东西看起来就不太可做。

我们假设这一行有一个 1,我们把它摁死,然后其他位置任意选,会发现最后结果一定可以通过是否选这个 1 来控制成 1。

总结来说,只要有一个 1,那么这列的选择方案数就是 2n1

问题转化成把每一行看成一个二进制数,有多少方案使其异或和是0。

这个就非常经典了,用线性基即可。即 2nsiz 。(理解的话就是计算每次插入元素最后变成0的情况)

Knights Out

考虑这样一个问题,我们每次点的不是马的形状,而是只对自己和周围四个点影响应该怎么做?

这是一个入门很经典的题目,我们只需要枚举第一行的情况,然后会发现,假设第一行被固定了,在第一行的第 i 个还没有被翻转,那么只有它下面一个格子,也就是第二行第 i 个被点一下才能使它翻转过来。

这样就会发现第二行的格子是否要点其实被第一行的控制了,继续推广下去可以一直到最后一行。我们再检查最后一行是否全部能被反转(因为没有别的行能够把它翻转)即可。

这个过程可以用方程模拟,设 f[i][j] 表示这行是否被选择,那么以第一行为主元就可以推广到每个点,并在最后一行解方程。

回到马的问题,会发现其实是一个道理,我们这时候固定前两行和第一列,然后会发现在这些确定的情况下,第一行第一列只能最后被第三行第二列的格子翻转。同样列方程,主元法,解最后两行和最右边一行的情况即可。

高斯消元部分,在一般 No solution 的位置 cnt+1 答案就是 2cnt

P4151 【WC2011】\surd$

这样思考一个问题,我们现在已经有一条路径了,我们怎么让它更优?

可能会说选择中间两个点,让他们出去绕一圈回来!

确实不假,那一个点呢?

一个点其实也可以优化,我们让这个点出去到一个环的位置,围着环绕一圈,然后原路返回,路上的值恰好被抵消了。

我们再想一下,这两个方法有什么本质上的不同吗?或者说有什么相同点?

合并起来,会发现都是选择一个环,不管有没有与原路径重合,把原来的值异或上这个环的值。

这时候我们就看到想要的形式了,我们找出来图里面的环,并且随便选择一条路径,把换线性基一下找异或最大值即可!

具体实现方面跑一棵生成树即可。

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