• 【GDOI2017 day2】凡喵识图 二进制切分


    题面


    100

    有一个显然的做法是(O(n^2))
    想办法优化这个做法:
    我们给一个64位整数,切分成四个16位整数。
    那么如果两个64位整数符合汉明距离为3的话,那么两者切分的四个16位整数中;
    至少存在一个16位整数相等。
    那么我们用这个16位整数为引索,遍历所有可能的,就能优化遍历次数了。
    由于数据近似随机,所以这个方法是可以过的。

    Code

    #include<bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define fo(i,x,y) for(int i=x;i<=y;i++)
    #define fd(i,x,y) for(int i=x;i>=y;i--)
    using namespace std;
    const int inf=0x7fffffff;
    const char* fin="2.in";
    const char* fout="2.out";
    const int maxn=150007,maxh=maxn*3+7;
    int n,ne[maxn][4],id,bz[maxn];
    ull a[maxn][4],b[maxn];
    map<ull,int> mp[4];
    bool judge(ull a,ull b){
    	ull c=a^b;
    	int x=0;
    	while (c){
    		if (++x>3) return false;
    		c-=c&-c;
    	}
    	return x==3;
    }
    int main(){
    	freopen(fin,"r",stdin);
    	freopen(fout,"w",stdout);
    	scanf("%d",&n);
    	ull m=1<<16;
    	fo(i,1,n){
    		ull x;
    		id++;
    		scanf("%llu",&x);
    		b[i]=x;
    		int ans=0;
    		fo(j,0,3) a[i][j]=x%m,x/=m;
    		fo(j,0,3){
    			if (mp[j].find(a[i][j])!=mp[j].end()){
    				int k=mp[j][a[i][j]];
    				ne[i][j]=k;
    				for(;k;k=ne[k][j]){
    					if (bz[k]==id) continue;
    					bz[k]=id;
    					if (judge(b[i],b[k])) ans++;
    				}
    			}mp[j][a[i][j]]=i;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    面试题-代码
    面试题-数仓
    烂大街的NginxRedisMqDb架构.md
    Ansible-B站.md
    openstack.md
    rabbitMQ.md
    大数据仓库实战项目-电商数仓3.0版.md
    linux分析工具之top命令详解
    小程序开发中 在 wxml格式化 属性断行
    redhat 7.2更新yum源时踩的坑
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6815189.html
Copyright © 2020-2023  润新知