我是参考了这篇文章点击打开链接
接下来我讲几个比较关键的点。
1.n*m的大矩阵总的有(n+1)*n*(m+1)*m/4;
2.颜色是从0开始依次累加的。
3.这个符合要求的子矩阵存储用int 会爆掉,(这个我估算错了一次。。。)
进过这两次比赛(我是小白),感觉杭电喜欢考容斥还有贡献和问题(我认为是一类 A占有B 但是却反过来计算从B被多少A占有,就像这道题)。
这样的题目其实不是很难,起码比起那些考数学的好多了(数学渣)。
继续加油。
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int mp[105][105];
vector<int> qur[105][105*105];
int main()
{
freopen("fuck.txt","r",stdin);
int T;
scanf("%d",&T);
for(int Case=1;Case<=T;Case++)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=0;j<n*m;j++)
if(!qur[i][j].empty())
qur[i][j].clear();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&mp[i][j]);
qur[i][mp[i][j]].push_back(j);
}
}
double ans1=0;
double ans2=(n+1)*n*(m+1)*m/4;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int z=0,y=m+1,x=n-i+1;
for(int k=i;k>=1;k--)
{
if(k!=i&&mp[k][j]==mp[i][j]) break;
if(qur[k][mp[i][j]].size()>0)
{
int z1;
for(int l=0;l<qur[k][mp[i][j]].size()&&qur[k][mp[i][j]][l]<j;l++)
{
z1=qur[k][mp[i][j]][l];
z=max(z1,z);
}
}
if(k!=i)
{
int y1;
for(int r=qur[k][mp[i][j]].size()-1;r>=0&&qur[k][mp[i][j]][r]>j;r--)
{
y1=qur[k][mp[i][j]][r];
y=min(y1,y);
}
}
//printf("%d %d %d %d %d\n",i,j,x,j-z,y-j);
//printf("%d %d %d\n",i,j,(j-z)*(y-j)*x);
ans1+=(j-z)*(y-j)*x;
}
}
}
printf("%.9llf\n",ans1/ans2);
}
}
本文介绍了一种解决特定矩阵子集计数问题的算法,该算法通过容斥原理及贡献和思想,有效地计算出符合条件的子矩阵数量,并提供了一个详细的实现代码示例。
356

被折叠的 条评论
为什么被折叠?



