这道题理解题意后 可分两种方法:哈希或 M R A MRA MRA(最小表示法)
乱搞差分 然后直接做匹配
a
n
s
+
+
ans++
ans++ 就可以了
注意用一个数组维护哈希 代码量短 喜闻乐见 时间复杂度优秀
O
(
n
m
)
O(nm)
O(nm)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=505;
const int e=10007;
int n,m,p,ans;
int a[N],b[N],q[N],k[N];
int main(){
scanf("%d%d%d",&n,&m,&p);
q[0]=1;
for(int i=1;i<=m;i++)
q[i]=q[i-1]*e; //哈希
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
scanf("%d",&a[j]);
sort(a+1,a+m+1);
for(int j=1;j<=m;j++)
b[j]=a[j+1]-a[j]; //差分数组
b[m]=a[1]+p-a[m]; //最后一位
sort(b+1,b+1+m);
for(int j=1;j<=m;j++)
k[i]+=q[j]*b[j]; //放进哈希
for(int j=1;j<i;j++)
if(k[j]==k[i]) ans++; //统计
}
printf("%d",ans);
return 0;
}
还是跑最小表示法 然后乱搞差分 再做一些玄学的位移操作
(不写这个也可以 就是后面比较麻烦)
然后匹配 注意是整个字符串 不是单个字符 最后
a
n
s
+
+
ans++
ans++
时间复杂度
O
(
n
m
2
)
O(nm^2)
O(nm2)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define re register
using namespace std;
int n,a[1005],m,o,ans,b[1005][1005],c[1005][1005];
bool f;
int MRA(int x[]) //最小表示法
{
int i=1,j=2,k;
while(i<=m&&j<=m)
{
for(k=0;k<=m&&x[i+k]==x[j+k];k++);
if(x[i+k]>x[j+k])
{
i+=k+1;
if(i==j) i++;
}else{
j+=k+1;
if(i==j) j++;
}
}
return min(i,j);
}
int main(){
scanf("%d%d%d",&n,&m,&o);
for(re int i=1;i<=n;i++)
{
for(re int j=1;j<=m;j++) scanf("%d",&a[j]);
sort(a+1,a+m+1);
a[m+1]=a[1]+o;
for(re int j=1;j<=m;j++)
{
b[i][j]=a[j+1]-a[j];
b[i][j+m]=b[i][j]; //都是乱搞の差分
}
}
for(int i=1;i<=n;i++)
{
int p=MRA(b[i]);
for(re int j=p;j<=p+m-1;j++) c[i][j-p+1]=b[i][j]; //位移操作
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
f=1;
for(int k=1;k<=m;k++)
if(c[i][k]!=c[j][k]) //匹配
{
f=0;break;
}
if(f) ans++;
}
}
printf("%d",ans);
return 0;
}