zoukankan      html  css  js  c++  java
  • 一道构造题

    Problem

    给定一个(n imes m)的矩阵,每次可以对矩阵做以下操作:

    1、给矩阵的一行同时加上一个数(k)

    2、给矩阵的一列同时加上一个数(k)

    3、给矩阵的一条对角线同时加上一个数(k)。给定(t),即(forall j-i=t),满足的(a_{i,j})即为一条对角线。

    构造一种方案使得矩阵最后全为0。无解输出-1。

    (n,mleq 10^3)

    Solution

    这是一道构造题,我们来考查操作下不变的关系。

    考查一个(3 imes 3)的矩阵,可以发现:(a_{1,1}-a_{2,1}-a_{1,2}+a_{2,3}+a_{3,2}-a_{3,3})始终不变!

    在三类操作下,变化的值总是能被抵消掉!(将其黑白染色)

    所以只要能填好前两行和前两列,依据以上等式可以将全部矩阵推导出来。

    问题就变成:将前两行前两列通过三种操作变成0,判断剩下位置是否为0。如果为0,则肯定无解;反之则有解。

    那么现在如何将前两行前两列变成0?这个很简单,把(a_{1,1})(a_{2,2})变成0后,对于第一行和第一列的数字,利用操作三变成0;对于第二行第二列,利用一二操作,这样可以不影响到(a_{1,1})(a_{1,2})

    #include <bits/stdc++.h>
    typedef long long LL;
    const int N = 1005;
    int n, m, a[N][N];
    LL x[N], y[N], z[N*2];
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++)
    			scanf("%d", &a[i][j]);
    	x[1] = a[2][2]-a[1][1]; z[n] = -a[2][2];
    	for (int i = 2; i <= n; i++) z[n-i+1] = -(a[i][1]+x[i]), x[i+1] = -(a[i+1][2]+z[n-i+1]);
    	for (int i = 2; i <= m; i++) z[n+i-1] = -(a[1][i]+x[1]+y[i]), y[i+1] = -(a[2][i+1]+z[n+i-1]);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++)
    			if (a[i][j]+x[i]+y[j]+z[j-i+n]) { puts("-1"); return 0; }
    	printf("%d
    ", 2*(n+m)-1);
    	for (int i = 1; i <= n; i++) printf("1 %d %lld
    ", i, x[i]);
    	for (int i = 1; i <= m; i++) printf("2 %d %lld
    ", i, y[i]);
    	for (int i = 1; i <= n+m-1; i++) printf("3 %d %lld
    ", i-n, z[i]);
    	return 0;
    }
    
  • 相关阅读:
    HTML基础
    一次由任意文件漏洞开始的渗透测试过程
    谈一谈信息泄露这件事
    浅谈任意文件下载漏洞的利用
    [原创] 一次渗透测试过程--从外网进内网
    一次绕过360+诺顿的提权过程
    漏洞挖掘高级方法
    新型勒索软件Magniber正瞄准韩国、亚太地区开展攻击
    Microsoft Edge 浏览器远程代码执行漏洞POC及细节(CVE-2017-8641)
    Office远程代码执行漏洞CVE-2017-0199复现
  • 原文地址:https://www.cnblogs.com/ac-evil/p/14015394.html
Copyright © 2011-2022 走看看