Snowflake snowflake

Posted by LordTyphon on Wed, 16 Oct 2019 22:31:54 +0200

Snowflake snowflake

N cyclic hexatuples \ (\ {a  1, a  2, a  3, a  4, a  5, a ) \) are given. Ask if there are two identical sextuples, \ (n\leq 100000 \).

solution

To think about using hash to discretize, the problem lies in the handling of rings. Let the subscript of six tuple elements start from 0, because it is convenient for modules to represent rings. Set the hash function \ (H (a ﹐ 0, a ﹐ 1, a ﹐ 2, a ﹐ 3, a ﹐ 4, a ﹐ 5) = \ sum {I = 0} ^ 5A ﹐ I + \ prod {I = 0} ^ 5A ﹐ I \).

For two identical hash values, ring splitting and chain forming, the starting point of enumeration chain, attention should be paid to not only clockwise enumeration, but also counter clockwise enumeration (drawing a picture is clear). When enumerating, analog ring is realized by module (see the code for details).

Reference code:

Unpackaged

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define ll long long
#define gzy 526619
using namespace std;
struct snowflake{
    int a[6];
}hl;
struct data{
    data*next;snowflake d;
}*head[gzy],*pt;
il void read(int&);
il int Hash(snowflake&);
il bool insert(snowflake&),
    equal(snowflake&,snowflake&);
int main(){
    int n;read(n);
    for(int i(1),j;i<=n;++i){
        for(j=0;j<6;++j)
            read(hl.a[j]);
        if(insert(hl))
            return puts("Twin snowflakes found."),0;
    }puts("No two snowflakes are alike.");
    return 0;
}
il int Hash(snowflake&x){int ans(1);
    for(ri int i(0);i<6;++i)
        ans=(ll)x.a[i]*ans%gzy;
    for(ri int i(0);i<6;++i)
        ans=(ans+x.a[i])%gzy;
    return ans;
}
il bool equal(snowflake &a,snowflake &b){
    for(ri int i(0),j,k;i<6;++i)
        for(j=0;j<6;++j){
            for(k=0;k<6;++k)
                if(a.a[(i+k)%6]!=b.a[(j+k)%6])break;
            if(k==6)return true;
            for(k=0;k<6;++k)
                if(a.a[(i+k)%6]!=b.a[(j-k+6)%6])break;
            if(k==6)return true;
        }return false;
}
il bool insert(snowflake&x){int H(Hash(x));
    for(pt=head[H];pt!=NULL;pt=pt->next)
        if(equal(x,pt->d))return true;
    pt=new data,pt->next=head[H],head[H]=pt;
    return pt->d=x,false;
}
il void read(int &x){
    x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

encapsulation

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define ll long long
#define gzy 491039
using namespace std;
il void read(int&);
template<class free>
struct unordered_map{
    struct data{
        data*next;free v;
    }*head[gzy],*pt;
    il void insert(free x){
        ri int key(x%gzy);
        pt=new data,pt->v=x;
        pt->next=head[key];
        head[key]=pt;
    }
    il data* find(free x){
        for(pt=head[x%gzy];pt!=NULL;pt=pt->next)
            if(pt->v==x)return pt;return NULL;
    }
};
struct snow{
    int a[6];
    il int operator%(int psj){int ans(1);
        for(ri int i(0);i<6;++i)
            ans=(ll)ans*a[i]%psj;
        for(ri int i(0);i<6;++i)
            ans=(ans+a[i])%gzy;
        return ans;
    }
    il bool operator==(snow x){
        ri int i,j,k;
        for(i=0;i<6;++i)
            for(j=0;j<6;++j){
                for(k=0;k<6;++k)
                    if(a[(i+k)%6]!=x.a[(j+k)%6])break;
                if(k==6)return true;
                for(k=0;k<6;++k)
                    if(a[(i-k+6)%6]!=x.a[(j+k)%6])break;
                if(k==6)return true;
            }return false;
    }
    il void read(){
        for(ri int i(0);i<6;++i)::read(a[i]);
    }
}hl;unordered_map<snow>U;
int main(){
    int n;read(n);
    for(int i(1);i<=n;++i){
        hl.read();
        if(U.find(hl)==NULL)U.insert(hl);
        else return puts("Twin snowflakes found."),0;
    }puts("No two snowflakes are alike.");
    return 0;
}
il void read(int &x){
    x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

Topics: PHP