Gym Conference Room (最小表示法,哈希)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
const int base=10007;
typedef unsigned long long ULL;
set<ULL>save;
int n;
int a[4][maxn],b[maxn];
int id[maxn<<1];
int ave;
ULL B[maxn];
int MinmumRepresentation(int *s,int n){
    int i=0,j=1,k=0,t;
    while(i<n&&j<n&&k<n){
        t=s[(i+k)>=n?i+k-n:i+k]-s[(j+k)>=n?j+k-n:j+k];
        if(!t)k++;
        else {
            if(t>0)i=i+k+1;
            else j=j+k+1;
            if(i==j)++j;
            k=0;
        }
    }
    return(i<j?i:j);
}
ULL gethash(int *s,int n){
    int pos=MinmumRepresentation(s,n);
    ULL res=0;
    for(int i=0;i<n;i++)res=res*base+s[id[pos+i]];
    return res;
}
bool legal(int x){
    return x>=2&&x<=ave-2;
}
bool ok(int d){
    for(int j=0;j<n;j++){
        b[j]=ave-a[2][j]-a[3][id[j+d]];
        if(!legal(b[j]))return 0;
    }
    return save.find(gethash(b,n))!=save.end();
}
int main(){
//    freopen("in","r",stdin);
    B[0]=1;
    for(int i=1;i<maxn;i++)B[i]=B[i-1]*base;
    int t,cas=1;
    cin>>t;
    while(t--){
        printf("Case %d: ",cas++);
        scanf("%d",&n);
        ULL sum=0;
        for(int i=0;i<4;i++)
        for(int j=0;j<n;j++){
            scanf("%d",a[i]+j);
            sum+=a[i][j];
        }
        if(sum%n){
            puts("No");
            continue;
        }
        ave=sum/n;
        save.clear();
        for(int i=0;i<2*n;i++)id[i]=i%n;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                b[j]=a[0][j]+a[1][id[i+j]];
            }
            save.insert(gethash(b,n));
        }
        bool flag=0;
        for(int i=0;i<n;i++){
            if(ok(i)){
                flag=1;
                puts("Yes");
                break;
            }
        }
        if(!flag)puts("No");
    }
    return 0;
}
时间: 2024-10-14 10:07:30

Gym Conference Room (最小表示法,哈希)的相关文章

HDU 4162 Shape Number(字符串,最小表示法)

HDU 4162 题意: 给一个数字串(length <= 300,000),数字由0~7构成,求出一阶差分码,然后输出与该差分码循环同构的最小字典序差分码. 思路: 第一步是将差分码求出:s[i] = (s[i] - s[i+1] + 8) % 8; 第二步是求出最小字典序的循环同构差分码,我之前没注意到字符串规模..直接用set做,MLE+TLE... 正确的方式应该是一种O(n)的解法,即最小表示法.//关于最小表示法的证明与详述请参考最小表示法:) 最小表示法算法: 初始时,i=0,j=

最小表示法(模板)

最小表示法就是对于一个循环字符串,其字典序最小的状态: 显然任意一个循环串的最小表示法是唯一的,那么可以同过比较两个循环串的最小表示法来判断它们是否相同: 对于朴素算法: 初始化:i = 0, j = 1, k = 0; 若 s[i] < s[j],j++: 若 s[i] > s[j],i = j, j++: 若 s[i] == s[j],则 k++,直至 s[i + k] != s[j + k] 对于 s[i + k] < s[j + k],j++: 否则 i = j, j++: 返回

USACO 5.5.2 字符串的最小表示法

这道题是最小表示法的一个应用, 代码如下: /* ID: m1500293 LANG: C++ PROG: hidden */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; char s[100000 + 100]; int len; int mins(char s[], int len) { int i=0, j=1, k=0; while(i<len

【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开的位置在哪一横排,将这一排提到排序后的字符串数组最前面,求个"最大表示法",如果最大表示法的位置恰好在第一排的位置,那么可以用来更新答案. 如果不在第一排的位置,那么其所构成的仍然是合法的串,而且一定不会影响答案. 这是一个最小表示法的板子. #include<cstdio>

BZOJ 2176 Strange string 最小表示法

题目大意:给定一个串S,求最小表示法 n<=1000W,实在不敢写后缀自己主动机,就去学了最小表示法= = 记得用unsigned char不然WA= = 数据真是逗- - #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 10001000 using namespace std; int n; unsigned char s[

循环字符串最大最小表示法模版

循环字符串最大最小表示法模版 定义字符串abcde和cdeab同构,因为abcde转两格即为cdeab,该字符串称为循环字符串. 循环字符串的字典序最小的同构字符串称为最小表示,最大表示同理. 这里只给模版,以后再深究. int getMin(char *s) ///返回首位置 { int n=strlen(s); int i=0,j=1,k=0; while(i<n&&j<n&&k<n){ int t=s[(i+k)%n]-s[(j+k)%n]; if(

hdu 2609 How many 最小表示法

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1248    Accepted Submission(s): 486 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100

51nod1282(最小表示法&amp;&amp;枚举)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1282 题意:中文题目诶- 思路:指针不可转,刻盘可转,显然,对于两组指针,当且仅当它们所有对应相邻指针间距都相等时是满足题意的: 先得到指针间距,因为刻盘可转,相当于循环数组,可以先求一下最小表示法,然后再两两枚举所有情况,对于最小表示法相同的两组指针,计数加一: 代码: 1 #include <iostream> 2 #include <algori

HDU 2609 How many (最大最小表示法)

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2184    Accepted Submission(s): 904 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100