分析
这题一开始是没啥思路的。
后面听讲了原来核心是求最小表示。最小表示模板
两两枚举圆盘并比较后就可以做到优秀的
O
(
n
m
2
log
2
m
+
n
2
m
)
O(nm^2\log_2m+n^2m)
O(nm2log2m+n2m)
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[501][1001],n,m,p,ans;
int main()
{
int x,y,z;
cin>>n>>m>>p;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++)
{
sort(a[i]+1,a[i]+m+1);
x=a[i][1];
for(int j=1;j<m;j++)
{
a[i][j]=a[i][j+1]-a[i][j];
}
a[i][m]=x-a[i][m]+p;
for(int j=1;j<=m;j++)//复制一遍放到后面
{
a[i][j+m]=a[i][j];
}
x=1;y=2;
while(x<=m&&y<=m)//最小表示模板
{
for(z=0;z<m&&a[i][x+z]==a[i][y+z];z++)//判断第一个不同
if(z==m)break;
if(a[i][x+z]>a[i][y+z])
{
x+=z+1;
if(x==y) x++;
}
else
{
y+=z+1;
if(x==y) y++;
}
}
z=min(x,y);
for(int j=0;j<m;j++)
{
a[0][j+1]=a[i][j+z];//把最小表示移到最前面
}
for(int j=1;j<=m;j++)//每位比对
{
a[i][j]=a[0][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
x=1;
for(int k=1;k<=m;k++)
{
if(a[i][k]!=a[j][k])
{
x=0;
break;
}
}
if(x) ans++;
}
}
cout<<ans;
return 0;
}