洛谷 P7515 - [省选联考 2021 A 卷] 矩阵游戏(差分约束)
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}\),那么
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 卷] 矩阵游戏(差分约束)的更多相关文章
- [省选联考 2021 A 卷] 矩阵游戏
很巧妙的一个构造. 我是没有想到的. 自己的思维能力可能还是不足. 考虑先满足\(b\)对\(a\)的限制,把\(a\)的第一行和第一列设\(0\),推出这个\(a\). 接下来考虑对这个\(a\), ...
- 洛谷 P7520 - [省选联考 2021 A 卷] 支配(支配树)
洛谷题面传送门 真·支配树不 sb 的题. 首先题面已经疯狂暗示咱们建出支配树对吧,那咱就老老实实建呗.由于这题数据范围允许 \(n^2\) 算法通过,因此可以考虑 \(\mathcal O(n^2 ...
- 洛谷 P7516 - [省选联考 2021 A/B 卷] 图函数(Floyd)
洛谷题面传送门 一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?) u1s1 现在已经是 \(1\text{s}\) \(10^9\) 的时代了吗?落伍了落伍了/ ...
- 洛谷P6623——[省选联考 2020 A 卷] 树
传送门:QAQQAQ 题意:自己看 思路:正解应该是线段树/trie树合并? 但是本蒟蒻啥也不会,就用了树上二次差分 (思路来源于https://www.luogu.com.cn/blog/dengy ...
- 洛谷 P6624 - [省选联考 2020 A 卷] 作业题(矩阵树定理+简单数论)
题面传送门 u1s1 这种题目还是相当套路的罢 首先看到 \(\gcd\) 可以套路地往数论方向想,我们记 \(f_i\) 为满足边权的 \(\gcd\) 为 \(i\) 的倍数的所有生成树的权值之和 ...
- [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂
题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...
- [省选联考 2021 A/B 卷] 卡牌游戏
垃圾福建垫底选手来看看这题. 大家怎么都写带 \(log\) 的. 我来说一个线性做法好了. 那么我们考虑枚举 \(k\) 作为翻转完的最小值. 那么构造出一个满足条件的操作,我们在 \(a_i\) ...
- [省选联考 2020 A 卷] 组合数问题
题意 [省选联考 2020 A 卷] 组合数问题 想法 自己在多项式和数论方面还是太差了,最近写这些题都没多少思路,看完题解才会 首先有这两个柿子 \(k*\dbinom{n}{k} = n*\dbi ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
随机推荐
- [no code][scrum meeting] Alpha 14
项目 内容 会议时间 2020-04-22 会议主题 周中讨论会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalog() ...
- BUAA SE | 提问回顾与个人总结
项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 提问回顾与个人总结 我在这个课程的目标是 深入理解软件工程 这个作业在哪个具体方面帮助我实现目标 ...
- 热身训练1 Problem B. Harvest of Apples
http://acm.hdu.edu.cn/showproblem.php?pid=6333 题意: 求 C(0,n)+C(1,n)+...+C(m,n) 分析: 这道题,我们令s(m,n) = C( ...
- 六个好习惯让你的PCB设计更优
PCB layout工程师每天对着板子成千上万条走线,各种各样的封装,重复着拉线的工作,也许很多人会觉得是很枯燥无聊的工作内容.看似软件操作搬运工,其实设计人员在过程中要在各种设计规则之间做取舍,兼顾 ...
- linux下创建文件的文件权限问题
今天发现创建文件的权限和自己规定的权限不一致,了解到了权限掩码的问题,这里总结一下. 首先权限掩码umask是chmod配套的,总共为4位(gid/uid,属主,组权,其它用户的权限),不过通常我们都 ...
- Python Numpy matplotlib Histograms 直方图
import numpy as np import matplotlib.pyplot as plt mu,sigma = 2,0.5 v = np.random.normal(mu,sigma,10 ...
- populating-next-right-pointers-in-each-node-ii leetcode C++
Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...
- SpringCloud概念
SpringCloud概述 1.SpringCloud是什么? 官方解释: 官网: https://spring.io/projects/spring-cloud/ SpringCloud是一系列 ...
- 三. 为什么要用Promise
# 三. 为什么要用Promise /* 1.指定回调函数的方式更加灵活: 旧的:必须在启动异步任务前指定 promise:启动异步任务 => 返回promie对象 => 给promise ...
- SqlServer新建表操作DDL
创建新表:1,五要素 2,not null 3,默认值 4,字段注释,表名称 5,索引 6,指定约束名称 -- ------------------------------ Table structu ...