有N个时钟,每个时钟有M个指针,P个刻度。时钟是圆形的,P个刻度均分整个圆。每个时钟每个指针指向整数刻度,并且每个时钟自身指针指向的数字都不同。你可以任意旋转时钟的表盘,但是你不能转指针。问最后有多少对时钟可以变成相同的状态。
例如:N = 5,M = 2,P = 4,5个时钟的数据如下{1, 2} {2, 4} {4, 3} {2, 3} {1, 3}

经过旋转后。 其中(1, 3), (1, 4), (2, 5) 和 (3, 4)是相同的。

给出所有时钟的数据,求有多少对时钟是相同的。
Input
第1行:3个数N, M, P中间用空格分隔,其中N为时钟的数量,M为表针的数量,P为刻度的数量(1 <= M, N <= 500, 1 <= P <= 10^9, M <= P)。 第2 - N + 1行:每行M个数,对应一个时钟,M个指针的位置。
Output
输出有多少对时钟是相同的。
Input示例
5 2 4 1 2 2 4 4 3 2 3 1 3
Output示例
4
首先对于询问有多少对相同的,我们只需要对当前表看看之前有没有相同的,如果有,就ans加上那个相同的个数即可。这样来计算。
对于每个表,我们要进行哈希处理。如何哈希呢,题目要求表的相对位置相同即可,也就是说我们不能根据每个表头指向的数字来进行判断。我们用每个表头之间的差值。因为相对位置相同的表,它的每个表头之间的差值一定是一样的。对于当前表,我们先排好序,这样找差值才是正确的。我们计算出所有的差值。把差值放到一个数组当中。这时我们要利用最小表示法,找到一个出发点坐标,从这个坐标的数开始的字符串是最短的。我们这样规定,哈希会更准确的。找到出发点之后s=11000*s+val[i]。这样得到一个s,这个s就代表了这个差值集合。 询问mp【s】,看看之前是否有相同的,ans+=mp【s】。之后mp【s】+1.
询问完所有的表之后输出ans即可。
#include<iostream> #include<stdio.h> #include<algorithm> #include<math.h> #include<map> #include<string.h> using namespace std; int n,m,p; int a[1100][1100]; int b[1100][1100]; map<long long ,int>mp; int getmin(int *s) { int i = 0, j = 1, k = 0; while(i<m && j<m && k<m) { int t = s[(i+k)%m]-s[(j+k)%m]; if (!t) k++; else { if (t>0) i += k+1; else j += k+1; if (i==j) j++; k = 0; } } return i<j?i:j; } int main() { cin>>n>>m>>p; int ans=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { cin>>a[i][j]; } sort(a[i],a[i]+m); a[i][m]=a[i][0]+p; for(int j=0;j<m;j++) { b[i][j]=a[i][j+1]-a[i][j]; } int chufadian=getmin(b[i]); int t; int s=1; for(int j=0;j<m;j++) { t=(j+chufadian)%m; s=s*14000+b[i][t]; } ans+=mp[s]; mp[s]++; } cout<<ans<<endl; }