【GDOI2017 day2】凡喵识图

Description

【GDOI2017 day2】凡喵识图_第1张图片

Solution

这道题目十分的玄学,比赛时候就想到正解了(除了随机化的部分)。
暴力可以怎么做,可以先把数压成4位,然后每个位置存储与这个二进制相同的下标,然后暴力枚举。这样看起来就是 n2
由于数据是随机的(比赛的时候又告诉我1/3构造),所以我们压四位的时候,随机化一下,不要按顺序,这样就可以过了。
如果我1/3构造,全部都出相同的,这个方法就GG了,不知道出题人比赛的时候为什么要说这个不存在的东西。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
typedef unsigned long long ll;
const int maxn=420000;
int i,j,k,l,t,n,m,ans,o,y,z;
int w[5][20],p[80],a[maxn][80],q[5][66000];
int first[maxn*2],last[maxn*2],next[maxn*2],num,az[maxn];
bool bz[100];
ll x,er[80];
int de(int x,int y){return (y-1)*4+x;}
void add(int x,int y){
    last[++num]=y,next[num]=first[x],first[x]=num;
}
int main(){
    freopen("hashing.in","r",stdin);
    freopen("hashing.out","w",stdout);
    fo(i,1,4){
        fo(j,1,16){
            o=rand()%64+1;while(bz[o])o=rand()%64+1;bz[o]=1;
            w[i][++w[i][0]]=o;p[o]=i;
        }
        sort(w[i]+1,w[i]+17);
    }
    er[0]=1;fo(i,1,63)er[i]=er[i-1]*2;
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%llu",&x);ans=0;
        fo(j,1,64)if(x&er[j-1])a[i][j]=1;
        fo(j,1,4){
            y=0;fo(k,1,16)if(a[i][w[j][k]])y+=er[k-1];
            rep(k,de(j,y)){
                z=last[k]-270000;o=0;
                if(az[z]==i)continue;az[z]=i;
                fo(l,1,64){
                    if(a[i][l]!=a[z][l])o++;
                    if(o>3)break;
                }
                if(o==3)ans++;
            }
            add(de(j,y),i+270000);
        }
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(省选,暴搜)