题解:
标程:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int INF=1e7+10;
struct Node{
ll val,id;
};
bool cmp(Node a,Node b){
return a.val>b.val;
}
ll quick(ll a,int b){//快速幂求逆元
ll ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll r[INF];
Node node[2510*2510];
ll num[2510];//统计每行的剩余数字个数
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
int id=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>node[id++].val;//把二维数组压缩为一维排序
node[id-1].id=i;
}
}
sort(node,node+n*n,cmp);
ll sum=1;
ll ans=0;
for(int i=0;i<n;i++)num[i]=n,sum=sum*n%mod;
for(int i=0;i<n*n;i++){//从大到小循环数字,暴力枚举
int id=node[i].id;
sum=sum*quick(num[id],mod-2)%mod;//选中数字的这一行,不计入权重中,一行只能选一个
ans=(ans+sum*node[i].val%mod)%mod;//数字*权重
num[id]--;//此行退出一个数字
if(!num[id])break;//当有一行全部算完,证明没有其他数字大于这一行的数字
sum=sum*num[id]%mod;//将此行剩余数字返回权重中
}
ll fenmu=1;
for(int i=1;i<=n;i++)fenmu=fenmu*n%mod;//所有情况的分母
cout<<ans*quick(fenmu,mod-2)%mod;
}