您的当前位置:首页正文

【10.26模拟赛T2】圆盘【MRAと哈希】

2024-11-27 来源:个人技术集锦

分析:

这道题理解题意后 可分两种方法:哈希 M R A MRA MRA(最小表示法)

哈希:

乱搞差分 然后直接做匹配 a n s + + ans++ ans++ 就可以了
注意用一个数组维护哈希 代码量短 喜闻乐见 时间复杂度优秀 O ( n m ) O(nm) O(nm)

CODE:

#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;
} 
MRA:

还是跑最小表示法 然后乱搞差分 再做一些玄学的位移操作
(不写这个也可以 就是后面比较麻烦)
然后匹配 注意是整个字符串 不是单个字符 最后 a n s + + ans++ ans++
时间复杂度 O ( n m 2 ) O(nm^2) O(nm2)

CODE:

#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;
} 
显示全文