首页 > 其他分享 >CSP模拟 矩阵操作

CSP模拟 矩阵操作

时间:2024-09-10 16:06:00浏览次数:1  
标签:ch sum 矩阵 代入 tag cases CSP 模拟

涉及知识点:就是个推式子+贪心?

前言

感觉有点板,故记录一下以备后续所用。

题意

有两个 $ n\times m$ 的矩阵 \(A\) 和 \(B\),每次操作可以把 \(A\) 或者 \(B\) 的某一行/列全部 \(+1\),最少几次操作 \(A=B\)?

思路

首先想到的肯定是构造一个差分矩阵,即 \(D=B-A\),问题转化为从一个零矩阵开始每次某一行/列 \(+1\) 或 \(-1\),问多少次操作得到 \(D\)。这是因为在 \(A\) 上 \(+1\) 的操作可以等价为在 \(B\) 上 \(-1\) 的操作。注意:\(D\) 中可能有负数。

那么现在问题的规模就从涉及两个矩阵压缩到了一个矩阵上,我们定义 \(r_i\) 为 \(D\) 第 \(i\) 行的修改,\(c_i\) 为第 \(i\) 列的修改,同样的,\(r_i,c_i\) 也可能为负数。

我们先假设 \(D\) 是合法的,此时显然可以得到:

\[\begin{cases} r_i= D_{i,1}-c_1\\ c_i= D_{1,i}-r_1 \end{cases}\tag{1} \]

此时互相代入展开 \(c_1,r_1\):

\[\begin{cases} r_i= D_{i,1}-D_{1,1}+r_1\\ c_i= D_{1,i}-D_{1,1}+c_1 \end{cases}\tag{2} \]

我们就得到了 \(r_i,c_i\) 的表达式。

显然 \(D\) 合法的充要条件是 \(D_{i,j}=r_i+c_j\),我们代入 \((1)\) 得到:

\[D_{i,j}=D_{i,1}+D_{1,i}-(r_1+c_1)\tag{3} \]

同时我们也知道 \(r_1+c_1=D_{1,1}\),因此 \(D\) 合法的条件就是,对于每个 \(i\in[1,n],j\in[1,m]\) 都满足 \(D_{i,j}=D_{i,1}+D_{1,i}-D_{1,1}\)。

接下来我们来计算答案,显然答案为 \(\sum_{i=1}^n|r_i|+\sum_{i=1}^m|c_i|\),将 \(c_i\) 用 \((1)\) 中的表示代入,\(r_i\) 用 \((2)\) 中的表示代入,我们就得到了一个全部由 \(r_1\) 表示(其他都是常数)的式子:

\[Ans=\sum_{i=1}^n|D_{i,1}-D_{1,1}+r_1|+\sum_{i=1}^m|D_{1,i}-r_1|\tag{4} \]

于是我们会发现,这个式子可以转化为一个 \(\sum |r_1-\lambda|\) 的形式:

\[Ans=\sum_{i=1}^n|r_1-(D_{1,1}-D_{i,1})|+\sum_{i=1}^m|r_1-D_{1,i}|\tag{5} \]

那么此时,根据数学知识,\(r_1\) 取所有\(n+m\) 个 \(\lambda\) 的中位数即可。

代码

为了节约空间,没必要再新开一个 \(D\) 数组,故直接用 \(B\) 存储差分后的结果。

另外,在编码时,如果 \(n+m\) 为偶数,\(r_1\) 没必要严格取计算中间两个数的平均值,可以证明只要 \(r_1\) 的取值在这两个数之间(包含这两个数)答案都一样,因此随便取左边或者右边那个数就行。

#include<bits/stdc++.h>
#define getid(x,y) ((x-1)*m+y)
using namespace std;
template<class T>inline void rd(T &x){
    T res=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
    x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
    static char wtbuff[20];
    static int wtptr;
    if(x==0){
        putchar('0');
    }
    else{
        if(x<0){x=-x;putchar('-');}
        wtptr=0;
        while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
        while(wtptr--) putchar(wtbuff[wtptr]);
    }
    if(endch!='\0') putchar(endch);
}
typedef long long LL;
const int MAXN=1e5+5;
int n,m;
LL a[MAXN],b[MAXN],ans;
inline void solve(){
    rd(n);rd(m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            rd(a[getid(i,j)]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            rd(b[getid(i,j)]);
            b[getid(i,j)]-=a[getid(i,j)];
        }
    }
    // for(int i=1;i<=n;i++){
    //     for(int j=1;j<=m;j++){
    //         cout<<b[getid(i,j)]<<' ';
    //     }
    //     cout<<endl;
    // }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(b[getid(i,j)]!=b[getid(1,j)]+b[getid(i,1)]-b[getid(1,1)]){
                puts("-1");
                return;
            }
        }
    }
    vector<LL>vec;
    for(int i=1;i<=n;i++)
        vec.push_back(b[getid(1,1)]-b[getid(i,1)]);
    for(int i=1;i<=m;i++)
        vec.push_back(b[getid(1,i)]);
    nth_element(vec.begin(),vec.begin()+vec.size()/2,vec.end());
    LL x=vec[vec.size()/2];
    ans=0;
    for(auto it:vec){
        ans+=abs(it-x);
    }
    wt(ans,'\n');
}
int main(){
    int t;
    rd(t);
    while(t--){
        solve();
    }
    return 0;
}

标签:ch,sum,矩阵,代入,tag,cases,CSP,模拟
From: https://www.cnblogs.com/SkyNet-PKN/p/18406568

相关文章

  • 9.10 模拟赛(炼石计划 11 月 15日 CSP-S 十连测 #10)
    炼石计划11月15日CSP-S十连测#10【补题】-比赛-梦熊联盟(mna.wang)复盘所有题先都浏览了一遍。其中T1见过。但当时是乱搞过的。但怎么乱搞的忘了。那就先做T1。有\(60\)分送的。尝试重新思考乱搞以获取剩余的\(40\)分。中间看了一眼T3。想了一分钟左右就会......
  • 多线程模拟叫号看病
    //普通号publicclassNormalThreadextendsThread{privateintnum=20;publicintgetNum(){returnnum;}publicvoidsetNum(intnum){this.num=num;}publicNormalThread(Stringname,intnum){super(......
  • CSP模拟 取模
    最近开始写CSP模拟的题,实际上考的题一点也不CSP题意有一个长度为\(n\)的序列\(A\),\(0\leqA_i<k\),你可以每次选取一个区间,将区间内所有元素\(+1\),然后将区间内所有元素对\(k\)取模。问最少几次操作可以把序列中所有元素都变为\(0\)。思路假设现在有一个数列\([2,3,......
  • 每日OJ_牛客_单词倒排(字符串模拟)
    目录牛客_单词倒排(字符串模拟)解析代码牛客_单词倒排(字符串模拟)单词倒排__牛客网时间限制:C/C++1秒,其他语言2秒空间限制:C/C++32M,其他语言64M题目描述:对字符串中的所有单词进行倒排。说明:1、构成单词的字符只有26个大写或小写英文字母;2、非构成单词的字符均视为单词......
  • 51nod 1051 最大子矩阵和
    51nod1051最大子矩阵和可以用前缀和容斥优化到\(O(n^4)\),但是不够进行如下图操作:将每一列的数值都压缩到一维的数组上,就转换为求最大字段和问题,时间复杂度\(O(n^3)\)。看看代码就知道了。#include<bits/stdc++.h>usingnamespacestd;#definelllonglongintn,m;......
  • 信息学奥赛初赛天天练-87-NOIP2014普及组-完善程序-矩阵、子矩阵、最大子矩阵和、前缀
    1完善程序最大子矩阵和给出m行n列的整数矩阵,求最大的子矩阵和(子矩阵不能为空)。输入第一行包含两个整数m和n,即矩阵的行数和列数。之后m行,每行n个整数,描述整个矩阵。程序最终输出最大的子矩阵和。(最后一空4分,其余3分,共16分)比如在如下这个矩阵中:440-2-7......
  • “PLUS模型+“生态系统服务多情景模拟预测
    生态系统服务是人类直接或间接从生态系统中获得的惠益,在应对城市挑战和实施可持续发展方面发挥着至关重要的作用。随着全球城市化的快速发展, 频繁的人类活动导致了土地利用的快速变化,导致生态系统结构和功能的变化,影响生态系统服务的供应。因此,生态系统服务评估与未来城市土......
  • 短视频seo矩阵源码---MVC框架开发技术分享
    一.短视频矩阵源码数据库建立1.用户表(user):-用户ID(user_id)-用户名(username)-密码(password)-手机号(phone)-邮箱(email)2.账号表(account):二. MVC框架开发技术分享MVC(模型-视图-控制器)是一种常见的软件架构模式,用于将应用程序的不同部分分离开来,以实现更好的可维护性和......
  • 短视频矩阵系统源码----SaaS化技术开发方案
    一.短视频矩阵系统介绍短视频矩阵系统是一种用来管理和展示短视频的系统。它可以帮助用户快速浏览和观看大量的短视频内容,提供了多种功能和工具来帮助用户管理和优化短视频的播放体验。1.账号管理(覆盖抖音、快手、B站、视频号等平台)企业可将多平台多个账号进行统一授权管......
  • 【洛谷 P1996】约瑟夫问题 题解(数组+模拟+循环)
    约瑟夫问题题目描述个人围成一圈,从第一个人开始报数,数到的人出列,再由下一个人重新从开始报数,数到的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰名小朋友,而该题是全部出圈。输入......