• SP4354 【TWINSNOW


    这题可以哈希。

    可以按照普通的哈希表写,但是插入的时间复杂度比较大还可能被卡单模数哈希。

    考虑将每个雪花特征和对于某一个质数取模的余数分类,对于每一类中的数用循环 (O(n^2)) 判断 。质数取的大一些就可以减小每一类数的个数,从而保证了复杂度。

    关于判断,可以考虑暴力打表,反正没几种情况,而且类似循环展开的还能减小常数。

    
    bool check(int x,int y) {
    	for(rint i=0;i<6;++i) {
    		if(a[x][0]==a[y][i]&&a[x][1]==a[y][(i+1)%6]
    		 &&a[x][2]==a[y][(i+2)%6]&&a[x][3]==a[y][(i+3)%6]
    		 &&a[x][4]==a[y][(i+4)%6]&&a[x][5]==a[y][(i+5)%6])return 1;//顺时针
    		if(a[x][0]==a[y][i]&&a[x][1]==a[y][(i+5)%6]
    		 &&a[x][2]==a[y][(i+4)%6]&&a[x][3]==a[y][(i+3)%6]
    		 &&a[x][4]==a[y][(i+2)%6]&&a[x][5]==a[y][(i+1)%6])return 1;//逆时针
    	}
    	return 0;
    }
    

    关于取什么模数好:
    尽量把每个雪花分散开,所以取 (n) 左右。我取了99991,珂以通过.但是很显然可以卡成 (O(n^2))。。。

    还有一种方法,就是随机一个模数出来,这样就几乎不可能卡了。有一种方法(自己yy的,可能有更好的方法):先随机一个在指定范围内的数,然后判断是否为质数。不是就加一接着判断。由于质数比较密集,复杂度可以保证。

    这部分的代码大概长这样

    
    	srand(time(0));
    	mod=rand()*3+20000;
    	while(mod<90000||mod>100000)mod=rand()*3+20000;
    	while(!isprime(mod))++mod;
        
    

    由于区间跨度是10000,有3333种rand到的数可以在这个区间,rand的值域是32768,概率大概是 (dfrac{1}{10}) ,很快就可以rand到区间内。

    这种随机模数的方法550ms,第4页。直接取99991是460ms,第3页,跑的应该不算慢了,而且码量不大,没压行60行不到。

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cmath>
    #include<cstdlib>
    #include<ctime>
    using namespace std;
    #define rint register int
    typedef long long LL;
    inline int rd(){
       int x=0,f=1;
       char ch=getchar();
       while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
       while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
       return x*f;
    }
    int mod;
    const int N=120010;
    int a[N][7],n;
    vector<int>v[N];
    bool check(int x,int y) {
    	for(rint i=0;i<6;++i) {
    		if(a[x][0]==a[y][i]&&a[x][1]==a[y][(i+1)%6]
    		 &&a[x][2]==a[y][(i+2)%6]&&a[x][3]==a[y][(i+3)%6]
    		 &&a[x][4]==a[y][(i+4)%6]&&a[x][5]==a[y][(i+5)%6])return 1;
    		if(a[x][0]==a[y][i]&&a[x][1]==a[y][(i+5)%6]
    		 &&a[x][2]==a[y][(i+4)%6]&&a[x][3]==a[y][(i+3)%6]
    		 &&a[x][4]==a[y][(i+2)%6]&&a[x][5]==a[y][(i+1)%6])return 1;
    	}
    	return 0;
    }
    bool isprime(int n){
    	if(n==1)return false;
    	if(n==2||n==3||n==5)return true;
    	if(n%6!=1&&n%6!=5)return false;
    	for(int i=5,mx=sqrt(n);i<=mx;++i)
    	if((n%i==0)||(n%(i+2)==0))return false;
    	return true;
    }
    int main() {
    	srand(time(0));
    	mod=rand()*3+20000;
    	while(mod<90000||mod>100000)mod=rand()*3+20000;
    	while(!isprime(mod))++mod;
    	//mod=99991; 
    	n=rd();
    	for(rint i=0;i<n;++i)
    		for(rint j=0;j<6;++j)
    			a[i][j]=rd();
    	long long sum;
    	for(rint i=0;i<n;++i) {
    		sum=0;
    		for(rint j=0;j<6;++j)sum+=a[i][j];
    		sum%=mod;
    		for(rint j=0;j<v[sum].size();++j)
    			if(check(i,v[sum][j]))return puts("Twin snowflakes found."),0;
    		v[sum].push_back(i);
    	}
    	return puts("No two snowflakes are alike."),0;
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    CART分类回归树算法
    决策分类树算法之ID3,C4.5算法系列
    break case
    Linux下创建C函数库
    邮件服务
    mysql 语句 GROUP_CONCAT
    python的__mro__与__slot__
    mod_wsgi 的两种模式
    看一看
    【转贴】Linux下MySQL 5.5的修改字符集编码为UTF8(彻底解决中文乱码问题)
  • 原文地址:https://www.cnblogs.com/zzctommy/p/12918536.html
Copyright © 2020-2023  润新知