前言
这为啥能想到来着。
思路分析
首先你发现答案只和初态和末态有关。
于是可以考虑定义势能,答案为势能的减少量。
经过仔细读题后发现,每次我们选择在一行或者一列操作,那么每一行和每一列的势能都是相对独立的。
于是我们只需要考虑在一行进行操作的势能变化,一行的势能是本行所有元素的势能之和,原图的势能就是行势能与列势能之和。
我们设 \(f(x)\) 表示在行内位置为 \(x\) 的元素所具有的势能,如果我们操作 \(x_1,x_2,x_1<x_2\),那么我们有:
\[f(x_1)+f(x_2)-f(x_1+1)-f(x_2-1)=x_2-x_1-1
\]
我们需要构造势能函数 \(f(x)\) 满足上面的式子。
我们尝试对上面的式子进行一点变换。
\[f(x_1+1)-f(x_1)-(x_1+1)=f(x_2)-f(x_2-1)-x_2
\]
我们让左右两边都为 \(0\) 即可,也就是,
\[f(x_1+1)-f(x_1)=x_1+1
\]
不妨设 \(f(0)=0\),那么对于 \(f(x)\),我们有,
\[f(x)=\frac{x(x+1)}{2}
\]
然后就可以算初态和末态的势能了。
复杂度 \(O(nm)\)。
代码实现
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a,cnt1[205],cnt2[205],ans1,ans2;
signed main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a;cnt1[i]+=a,cnt2[j]+=a;}}for(int i=1;i<=n;i++){ans1+=i*(i+1)/2*cnt1[i];cnt1[i]=0;}for(int i=1;i<=m;i++){ans1+=i*(i+1)/2*cnt2[i];cnt2[i]=0;}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a;cnt1[i]+=a,cnt2[j]+=a;}}for(int i=1;i<=n;i++){ans2+=i*(i+1)/2*cnt1[i];cnt1[i]=0;}for(int i=1;i<=m;i++){ans2+=i*(i+1)/2*cnt2[i];cnt2[i]=0;}cout<<ans1-ans2;return 0;
}