• 51Nod 1282 时钟 —— 最小表示法 + 字符串哈希


    题目链接:https://vjudge.net/problem/51Nod-1282


    题目来源: Codility
    基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
     
    有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


    题解:

    1.对于每个时钟,计算所有相邻时针的间隔,然后用最小表示法表示。

    2.借助字符串哈希,将每个经过最小表示法处理后的时钟压缩成一个unsigne long long类型的数。

    3.使用map维护。


    代码如下:

     1 #include <bits/stdc++.h>
     2 #define rep(i,a,n) for(int (i) = a; (i)<=(n); (i)++)
     3 #define ms(a,b) memset((a),(b),sizeof((a)))
     4 using namespace std;
     5 typedef long long LL;
     6 const int INF = 2e9;
     7 const LL LNF = 9e18;
     8 const int mod = 1e9+7;
     9 const int maxn = 500+10;
    10 
    11 int a[maxn][maxn];
    12 int n,m,p;
    13 map<unsigned long long, int >mp;
    14 const unsigned long long seed = 13331;
    15 
    16 int getmin(int *s, int len) //返回最小表示法的始端
    17 {
    18     int i = 0, j = 1, k = 0;
    19     while(i<len && j<len && k<len)
    20     {
    21         int t = s[(i+k)%len]-s[(j+k)%len];
    22         if (!t) k++;
    23         else
    24         {
    25             if (t>0) i += k+1;
    26             else j += k+1;
    27             if (i==j) j++;
    28             k = 0;
    29         }
    30     }
    31     return i<j?i:j;
    32 }
    33 
    34 int main()
    35 {
    36     int ans = 0;
    37     cin>>n>>m>>p;
    38     for(int i = 0; i<n; i++)
    39     {
    40         for(int j = 0; j<m; j++)
    41             cin>>a[i][j];
    42 
    43         sort(a[i], a[i]+m);
    44         a[i][m] = a[i][0]+p;
    45         for(int j = 0; j<m; j++)    //获得间隔距离
    46             a[i][j] = a[i][j+1]-a[i][j];
    47 
    48         int k = getmin(a[i], m);    //k为始端
    49         unsigned long long s = 1;
    50         for(int j = 0; j<m; j++)
    51         {
    52             int t = (j+k)%m;
    53             s = 1LL*s*seed + 1LL*a[i][t];   //字符串哈希,seed相当于进制
    54         }
    55         ans += mp[s];   //统计对数
    56         mp[s]++;    //加入到map中
    57     }
    58     cout<<ans<<endl;
    59 }
    View Code



    一开始没有用字符串哈希,直接把数组用队列的形式丢进map中,也不会超内存。

     1 #include <bits/stdc++.h>
     2 #define rep(i,a,n) for(int (i) = a; (i)<=(n); (i)++)
     3 #define ms(a,b) memset((a),(b),sizeof((a)))
     4 using namespace std;
     5 typedef long long LL;
     6 const int INF = 2e9;
     7 const LL LNF = 9e18;
     8 const int mod = 1e9+7;
     9 const int maxn = 500+10;
    10 
    11 int a[maxn][maxn];
    12 int n,m,p;
    13 map< queue<int>, int >mp;   //把数组以队列的形式丢进map中
    14 
    15 int getmin(int *s, int len)
    16 {
    17     int i = 0, j = 1, k = 0;
    18     while(i<len && j<len && k<len)
    19     {
    20         int t = s[(i+k)%len]-s[(j+k)%len];
    21         if (!t) k++;
    22         else
    23         {
    24             if (t>0) i+=k+1;
    25             else j+=k+1;
    26             if (i==j) j++;
    27             k=0;
    28         }
    29     }
    30     return i<j?i:j;
    31 }
    32 
    33 
    34 int main()
    35 {
    36     int ans = 0;
    37     cin>>n>>m>>p;
    38     for(int i = 0; i<n; i++)
    39     {
    40         for(int j = 0; j<m; j++)
    41             cin>>a[i][j];
    42 
    43         sort(a[i], a[i]+m);
    44         a[i][m] = a[i][0]+p;
    45         for(int j = 0; j<m; j++)
    46             a[i][j] = a[i][j+1]-a[i][j];
    47 
    48         int k = getmin(a[i], m);
    49         queue<int>v;
    50         for(int j = 0; j<m; j++)
    51         {
    52             int t = (j+k)%m;
    53             v.push(a[i][t]);
    54         }
    55         ans += mp[v];
    56         mp[v]++;
    57     }
    58     cout<<ans<<endl;
    59 }
    View Code
  • 相关阅读:
    TApplication元件的OnIdle事件
    Query1AfterScroll 与 DataSource1DataChange 区别
    禁用表外键
    oracle al32utf8 字符长度
    Oracle表空间等操作
    delphi组件说明
    delhpi控件替换
    程序提示Google Internet Authority G2 证书不可用
    PostMessage用法
    OnKeyPress OnKeyDown区别
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7538624.html
Copyright © 2020-2023  润新知