题面传送门

emmm……怎么评价这个题呢,赛后学完差分约束之后看题解感觉没那么 dl,可是现场为啥就因为种种原因想不到呢?显然是 wtcl(

先不考虑“非负“及” \(\le 10^6\) ”这两条件,考虑什么样的矩阵 \(A\) 能够生成 \(B\),我们首先考虑矩阵 \(A\) 的一个特解 \(A'\):第一行和第一列都是 \(0\) 的情况,显然 \(A'\) 可以通过一遍反着递推求出。接下来考虑怎样通过 \(A'\) 推出所有符合要求的矩阵 \(A\),一个显然的事实是如果确定了该矩阵 \(A\) 的第一行和第一列,那么最终的矩阵就定下来了。注意到 \(A\) 的第一行第一列的元素 \(A_{11}\) 是有点特别的,因为它既在第一行又在第一列,我们先忽略它,暂且将它定为 \(0\)。我们考虑对于某个 \(i\ne 1\),将 \(A_{1i}\)(或 \(A_{i1}\))由 \(0\) 变为 \(v\) 对整个矩阵 \(A\) 产生的影响,以 \(A_{1i}\) 为例,手玩几组数据就可以发现若 \(A_{1i}\) 变成 \(v\),那么 \(A_{2i}\) 会减去 \(v\),\(A_{3i}\) 会加上 \(v\),\(A_{4i}\) 又会减去 \(v\),以此类推。我们假设 \(x_i=A_{i1},y_i=A_{1i}\),那么

\[A=A'+\begin{bmatrix}
0&y_2&y_3&\cdots&y_j&\cdots&y_m\\
x_2&-x_2-y_2&x_2-y_3&\cdots&(-1)^{j+1}x_2-y_j&\cdots&(-1)^{m+1}x_2-y_m\\
\vdots&\vdots&\vdots&\ddots&\vdots&\ddots&\vdots\\
x_i&-x_i+(-1)^{i+1}y_2&x_i+(-1)^{i+1}y_3&\cdots&(-1)^{j+1}x_i+(-1)^{i+1}y_j&\cdots&(-1)^{m+1}x_i+(-1)^{i+1}y_m\\
\vdots&\vdots&\vdots&\ddots&\vdots&\ddots&\vdots\\
x_n&-x_n+(-1)^{n+1}y_2&x_n+(-1)^{n+1}y_3&\cdots&(-1)^{j+1}x_n+(-1)^{n+1}y_j&\cdots&(-1)^{m+1}x_n+(-1)^{n+1}y_m
\end{bmatrix}
\]

考虑加上 \(A_{11}\) 之后的影响,那么 \(A_{ij}\) 会加上 \((-1)^{i+j+1}A_{11}\),这个看起来有点棘手,怎么办呢?我们考虑设 \(A_{11}=x_1+y_1\)(这个 \(x_1\) 可以为任意整数),我们令新的 \(x_i\leftarrow x_i+(-1)^{i}y_1\),再令新的 \(y_i\leftarrow y_i+(-1)^ix_1\),不难发现经过这样的转化之后,\(A_{i,j}\) 由原来的 \(A'_{i,j}+(-1)^{j+1}x_i+(-1)^{i+1}y_j\) 变为 \(A'_{i,j}+(-1)^{j+1}(x_i+(-1)^iy_1)+(-1)^{i+1}(y_j+(-1)^jx_1)=A'_{i,j}+(-1)^{j+1}x_i+(-1)^{i+1}y_j+(-1)^{i+j+1}(x_1+y_1)\)(注:该式子中的 \(x_i,y_i\) 为原来的 \(x_i,y_i\),下同)刚好就是新的 \(A_{i,j}\),但是这样第一行第一列的值就不对了,此时考虑再令 \(A_{i1}=x_i+(-1)^{i+1}y_1\),\(A_{1i}=y_i+(-1)^{i+1}x_1\),这样新的 \(A_{1i}=x_i+(-1)^{i}y_1+(-1)^{i+1}y_1\) 刚好就是原来的 \(x_i\),\(A_{i1}\) 也同理。因此新的 \(A_{i,j}=A'_{i,j}+(-1)^{j+1}x_i+(-1)^{i+1}y_j\),就不用考虑 \(i,j\) 是否为 \(1\),显然一组 \(x,y\) 对应一个生成 \(B\) 的矩阵 \(A\),而一个对于 \(A\) 又存在合法的 \(x,y\),因此我们只用求出合法的 \(x_i,y_j\) 即可构造出符合要求的 \(A\)

我们考虑 \(A_{i,j}\) 非负这个条件的具体作用,由于涉及 \((-1)^i\) 这种形式的东西,因此按 \(i,j\) 的奇偶性分类讨论:

  • \(i\) 为奇数,\(j\) 为奇数,\(0\le x_i+y_j+A'_{i,j}\le 10^6\)
  • \(i\) 为奇数,\(j\) 为偶数,\(0\le -x_i+y_j+A'_{i,j}\le 10^6\)
  • \(i\) 为偶数,\(j\) 为奇数,\(0\le x_i-y_j+A'_{i,j}\le 10^6\)
  • \(i\) 为偶数,\(j\) 为偶数,\(0\le -x_i-y_j+A'_{i,j}\le 10^6\)

中间两个都可通过某种方式转化为差分约束的标准形式,关键是前两个怎么处理,其实也比较 simple,我们令 \(x'_i=(-1)^{i+1}x_i,y'_i=(-1)^iy_i\),那么上面四种情况又可写作:

  • \(i\) 为奇数,\(j\) 为奇数,\(0\le x'_i-y'_j+A'_{i,j}\le 10^6\)
  • \(i\) 为奇数,\(j\) 为偶数,\(0\le -x'_i+y'_j+A'_{i,j}\le 10^6\)
  • \(i\) 为偶数,\(j\) 为奇数,\(0\le -x'_i+y'_j+A'_{i,j}\le 10^6\)
  • \(i\) 为偶数,\(j\) 为偶数,\(0\le x'_i-y'_j+A'_{i,j}\le 10^6\)

这下四个式子都可以转化为差分约束的形式了,直接差分约束建出图来判个负环即可。

时间复杂度 \(Tn^3\)

这里有一个小小的细节以前一直没有注意过,这里稍微提一下,就是判负环过程中的“松弛次数”只要 \(dis\) 值被更新了就行,不一定指“入队次数”,这样常数会小一些,否则对于 NO 的数据可能要跑很久,我一直为此 TLE 50,交了 \(114514191981019260817998244353\) 发(bushi)

代码异常好写:

const int MAXN=300;
const int MAXV=600;
const int MAXE=300*300*2;
int n,m,a[MAXN+5][MAXN+5],b[MAXN+5][MAXN+5];
int hd[MAXV+5],to[MAXE+5],nxt[MAXE+5],val[MAXE+5],ec=0;
void adde(int u,int v,int w){to[++ec]=v;val[ec]=w;nxt[ec]=hd[u];hd[u]=ec;}
bool inq[MAXV+5];ll dis[MAXV+5];int in[MAXV+5];
void clear(){
memset(b,0,sizeof(b));
memset(hd,0,sizeof(hd));ec=0;
memset(in,0,sizeof(in));
memset(dis,0,sizeof(dis));
memset(inq,0,sizeof(inq));//注意清空 inq 数组,因为有可能出现判到负环就 return 的清空,所以最后 inq[i] 不一定是 0
}
void solve(){
scanf("%d%d",&n,&m);clear();
for(int i=1;i<n;i++) for(int j=1;j<m;j++) scanf("%d",&a[i][j]);
for(int i=2;i<=n;i++) for(int j=2;j<=m;j++) b[i][j]=a[i-1][j-1]-b[i-1][j]-b[i][j-1]-b[i-1][j-1];
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
if(~(i+j)&1) adde(i,j+n,b[i][j]),adde(j+n,i,1e6-b[i][j]);//x[i]-y[j]
else adde(j+n,i,b[i][j]),adde(i,j+n,1e6-b[i][j]);//y[j]-x[i]
} queue<int> q;
for(int i=1;i<=n+m;i++) q.push(i),inq[i]=1;
while(!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=val[e];
if(dis[y]>dis[x]+z){
dis[y]=dis[x]+z;
if(++in[y]>n+m) return puts("NO"),void();//这边稍微注意下,不一定要写到下面一个 if 中
if(!inq[y]) q.push(y),inq[y]=1;
}
}
}
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
if(~(i+j)&1) b[i][j]+=dis[i]-dis[j+n];
else b[i][j]+=dis[j+n]-dis[i];
} printf("YES\n");
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%d%c",b[i][j]," \n"[j==m]);
}
int main(){int qu;scanf("%d",&qu);while(qu--) solve();return 0;}

洛谷 P7515 - [省选联考 2021 A 卷] 矩阵游戏(差分约束)的更多相关文章

  1. [省选联考 2021 A 卷] 矩阵游戏

    很巧妙的一个构造. 我是没有想到的. 自己的思维能力可能还是不足. 考虑先满足\(b\)对\(a\)的限制,把\(a\)的第一行和第一列设\(0\),推出这个\(a\). 接下来考虑对这个\(a\), ...

  2. 洛谷 P7520 - [省选联考 2021 A 卷] 支配(支配树)

    洛谷题面传送门 真·支配树不 sb 的题. 首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗.由于这题数据范围允许 \(n^2\)​ 算法通过,因此可以考虑 \(\mathcal O(n^2 ...

  3. 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)

    洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\)​ \(10^9\)​ 的时代了吗?落伍了落伍了/ ...

  4. 洛谷P6623——[省选联考 2020 A 卷] 树

    传送门:QAQQAQ 题意:自己看 思路:正解应该是线段树/trie树合并? 但是本蒟蒻啥也不会,就用了树上二次差分 (思路来源于https://www.luogu.com.cn/blog/dengy ...

  5. 洛谷 P6624 - [省选联考 2020 A 卷] 作业题(矩阵树定理+简单数论)

    题面传送门 u1s1 这种题目还是相当套路的罢 首先看到 \(\gcd\) 可以套路地往数论方向想,我们记 \(f_i\) 为满足边权的 \(\gcd\) 为 \(i\) 的倍数的所有生成树的权值之和 ...

  6. [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂

    题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...

  7. [省选联考 2021 A/B 卷] 卡牌游戏

    垃圾福建垫底选手来看看这题. 大家怎么都写带 \(log\) 的. 我来说一个线性做法好了. 那么我们考虑枚举 \(k\) 作为翻转完的最小值. 那么构造出一个满足条件的操作,我们在 \(a_i\) ...

  8. [省选联考 2020 A 卷] 组合数问题

    题意 [省选联考 2020 A 卷] 组合数问题 想法 自己在多项式和数论方面还是太差了,最近写这些题都没多少思路,看完题解才会 首先有这两个柿子 \(k*\dbinom{n}{k} = n*\dbi ...

  9. luoguP6623 [省选联考 2020 A 卷] 树(trie树)

    luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...

随机推荐

  1. 【c++ Prime 学习笔记】第4章 表达式

    表达式由一个或多个运算对象组成,对表达式求值返回结果. 字面值和变量是最简单的表达式 把运算符和运算对象组合可得到复杂表达式. 4.1 基础 4.1.1 基本概念 一元运算符作用于一个对象,如取地址符 ...

  2. reorder-list leetcode C++

    Given a singly linked list L: L 0→L 1→-→L n-1→L n, reorder it to: L 0→L n →L 1→L n-1→L 2→L n-2→- You ...

  3. Python matplotlib 概率论与数理统计 伯努利分布 二项分布

    Python 代码实现 二项分布 import numpy as np import matplotlib.pyplot as plt import math from scipy import st ...

  4. PHP笔记4__函数/全局、静态变量/函数参数/加载函数库/,,

    <?php header("Content-type: text/html; charset=utf-8"); echo table(5,5); function table ...

  5. 一步一步学ROP之linux_x64篇(蒸米spark)

    目录 一步一步学ROP之linux_x64篇(蒸米spark) 0x00 序 0x01 Memory Leak & DynELF - 在不获取目标libc.so的情况下进行ROP攻击 0x02 ...

  6. 恶意代码分析实战五:OllyDebug动态结合

    目录 恶意代码分析实战五:OllyDebug动态结合 OllyDebug界面介绍 OllyDebug载入程序方法 OllyDebug地址跳转 OllyDebug下断点 OllyDebug单步执行 Ol ...

  7. TDengine在浙商银行微服务监控中的实践

    作者:楼永红 王轩宇|浙商银行    浙商银行股份有限公司(简称"浙商银行")是 12 家全国性股份制商业银行之一,总部设在浙江杭州,全国第13家"A+H"上市 ...

  8. "迷途"的野指针,都快找不着北了

    指针,C语言开发者表示很淦,指针的使用,很多人表示不敢直面ta,不像Java一样,有垃圾自动回收功能,我们不用担心那么多内存泄漏等问题,那C语言里边呢,指针又分为了"野指针",&q ...

  9. C++ new 运算符 用法总结

    C++ new 运算符 用法总结 使用 new 运算符 分配内存 并 初始化 1.分配内存初始化标量类型(如 int 或 double),在类型名后加初始值,并用小括号括起,C++11中也支持大括号. ...

  10. MySQL高级篇 | 索引介绍

    前言 性能下降SQL慢的原因 查询语句写的烂 索引失效 单值索引 复合索引 关联查询太多join(设计缺陷或不得已的需求) 服务器调优及各个参数设置(缓冲.线程数等) 索引是什么 MySQL官方对索引 ...