51Nod 1282 时钟 —— 最小表示法 + 字符串哈希
题目链接:https://vjudge.net/problem/51Nod-1282


第1行:3个数N, M, P中间用空格分隔,其中N为时钟的数量,M为表针的数量,P为刻度的数量(1 <= M, N <= 500, 1 <= P <= 10^9, M <= P)。
第2 - N + 1行:每行M个数,对应一个时钟,M个指针的位置。
输出有多少对时钟是相同的。
5 2 4
1 2
2 4
4 3
2 3
1 3
4
题解:
1.对于每个时钟,计算所有相邻时针的间隔,然后用最小表示法表示。
2.借助字符串哈希,将每个经过最小表示法处理后的时钟压缩成一个unsigne long long类型的数。
3.使用map维护。
代码如下:
#include <bits/stdc++.h>
#define rep(i,a,n) for(int (i) = a; (i)<=(n); (i)++)
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; int a[maxn][maxn];
int n,m,p;
map<unsigned long long, int >mp;
const unsigned long long seed = ; int getmin(int *s, int len) //返回最小表示法的始端
{
int i = , j = , k = ;
while(i<len && j<len && k<len)
{
int t = s[(i+k)%len]-s[(j+k)%len];
if (!t) k++;
else
{
if (t>) i += k+;
else j += k+;
if (i==j) j++;
k = ;
}
}
return i<j?i:j;
} int main()
{
int ans = ;
cin>>n>>m>>p;
for(int i = ; i<n; i++)
{
for(int j = ; j<m; j++)
cin>>a[i][j]; sort(a[i], a[i]+m);
a[i][m] = a[i][]+p;
for(int j = ; j<m; j++) //获得间隔距离
a[i][j] = a[i][j+]-a[i][j]; int k = getmin(a[i], m); //k为始端
unsigned long long s = ;
for(int j = ; j<m; j++)
{
int t = (j+k)%m;
s = 1LL*s*seed + 1LL*a[i][t]; //字符串哈希,seed相当于进制
}
ans += mp[s]; //统计对数
mp[s]++; //加入到map中
}
cout<<ans<<endl;
}
一开始没有用字符串哈希,直接把数组用队列的形式丢进map中,也不会超内存。
#include <bits/stdc++.h>
#define rep(i,a,n) for(int (i) = a; (i)<=(n); (i)++)
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; int a[maxn][maxn];
int n,m,p;
map< queue<int>, int >mp; //把数组以队列的形式丢进map中 int getmin(int *s, int len)
{
int i = , j = , k = ;
while(i<len && j<len && k<len)
{
int t = s[(i+k)%len]-s[(j+k)%len];
if (!t) k++;
else
{
if (t>) i+=k+;
else j+=k+;
if (i==j) j++;
k=;
}
}
return i<j?i:j;
} int main()
{
int ans = ;
cin>>n>>m>>p;
for(int i = ; i<n; i++)
{
for(int j = ; j<m; j++)
cin>>a[i][j]; sort(a[i], a[i]+m);
a[i][m] = a[i][]+p;
for(int j = ; j<m; j++)
a[i][j] = a[i][j+]-a[i][j]; int k = getmin(a[i], m);
queue<int>v;
for(int j = ; j<m; j++)
{
int t = (j+k)%m;
v.push(a[i][t]);
}
ans += mp[v];
mp[v]++;
}
cout<<ans<<endl;
}
51Nod 1282 时钟 —— 最小表示法 + 字符串哈希的更多相关文章
- 1282 时钟(最小表示法+hash)
1282 时钟 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有N个时钟,每个时钟有M个指针,P个刻度.时钟是圆形的,P个刻度均分整 ...
- 51nod 1282 时钟
1282 时钟 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有N个时钟,每个时钟有M个指针,P个刻度.时钟是圆形的,P个刻度均分 ...
- 【字符串】【最小表示法】Vijos P1683 有根树的同构问题
题目链接: https://vijos.org/p/1683 题目大意: 给M棵树,每棵N个点,N-1条边,树边有向,问哪些树同构. 题目思路: [字符串][最小表示法] 用()表示一个节点,那么三个 ...
- HDU 4162 Shape Number(字符串,最小表示法)
HDU 4162 题意: 给一个数字串(length <= 300,000),数字由0~7构成,求出一阶差分码,然后输出与该差分码循环同构的最小字典序差分码. 思路: 第一步是将差分码求出:s[ ...
- BZOJ1398: Vijos1382寻找主人 Necklace 字符串最小表示法
Description 给定两个项链的表示,判断他们是否可能是一条项链. Input 输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的). Output 如果 ...
- HDU——2609How many(字符串的最小表示法+substr)
How many Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- POJ 1509 Glass Beads【字符串最小表示法】
题目链接: http://poj.org/problem?id=1509 题意: 求循环字符串的最小表示. 分析: 浅析"最小表示法"思想在字符串循环同构问题中的应用 判断两字符串 ...
- 牛客练习赛36 A Rabbit的字符串(字符串最小表示法)
链接:https://ac.nowcoder.com/acm/contest/328/A来源:牛客网 题目描述 Rabbit得到了一个字符串,她的好朋友xxx可以给这个字符串施加一次魔法. 魔法可以选 ...
- bzoj2176 Strange string(字符串最小表示法)
Time Limit: 10 Sec Memory Limit: 259 MB 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的 ...
随机推荐
- 线段树练习5(codevs 4927)
题目描述 Description 有n个数和5种操作 add a b c:把区间[a,b]内的所有数都增加c set a b c:把区间[a,b]内的所有数都设为c sum a b:查询区间[a,b] ...
- Virtualization基础
官方文档学习 https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/pdf/Virtualization_G ...
- Mongodb报错:ERROR: child process failed, exited with error number 1
Mongodb在启动时报错: 2018-10-16T11:18:54.533+0800 I CONTROL [main] Automatically disabling TLS 1.0, to for ...
- golang-uuid
uuid第三方库可以在github上找,我在这使用的是:github.com/satori/go.uuid PS:不知道哪里原因,使用go mod 管理包,下载的包和github上的不是完全一样,也特 ...
- BZOJ3786 星际探索
@(BZOJ)[DFS序, Splay] Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其 ...
- NIO与传统IO的区别(形象比喻)[转]
传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大.使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数 ...
- 3.JAVA语言基础部分—Class类与反射
什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...
- Java的不定参数(eg:Object...)(转)
第一个例子: public class VariArgs { public static void main(String[] args) { test(); test("aaa" ...
- ORACLE 内部原理
http://www.ohsdba.cn/index.php?m=Article&a=index&id=46 内部原理 2016-05-04• 如何使用BBED 2016-04-16• ...
- Object中的wait,notify,notifyAll基本使用(转)
让线程停止运行/睡眠的方法只有两个:Thread.sleep()或者obj.wait() 记住obj.nofity()并不能停止线程运行,因为notify虽然释放了锁,但依然会急促执行完synchro ...