假设我们按照某一种随机的规则在两个同源变形虫中取一个数,那么由于有l/2是相同的,因此概率为1/4。如果我们给每一个基因定一个值,然后定义一个变形虫的值就是它l个基因中的最小值,那么两个同源变形虫相同的概率就是1/3;两个不同源为1/l。如果取两个,就分别是1/9和1/l^2=1/n。
那么每次给每个基因随机定值,这样一次可以得到n/9对,不断操作即可。
AC代码如下:
#include<bits/stdc++.h> #define N 35005 #define M 4000005 using namespace std; int n,m,l,tot,pt,cnt,q1[M],q2[M],a[N][135],mrk[M],mch[N]; struct node{ int x,y,z; }b[N]; struct hsh{ int fst[2010527],pnt[M],nxt[M]; int ins(int x){ int y=x%2010527,p; for (p=fst[y]; p; p=nxt[p]) if (pnt[p]==x) return p; pnt[++tot]=x; nxt[tot]=fst[y]; fst[y]=tot; return tot; } }h; bool cmp(const node &u,const node &v){ return u.x<v.x || u.x==v.x && u.y<v.y; } bool eql(int x,int y){ pt++; int i,sum=0; for (i=1; i<=l; i++) mrk[a[x][i]]=pt; for (i=1; i<=l; i++) if (mrk[a[y][i]]==pt) sum++; return sum==(l>>1); } int solve(){ int i,j,u,v; cnt=0; random_shuffle(q1+1,q1+tot+1); random_shuffle(q2+1,q2+tot+1); for (i=1; i<=n; i++) if (!mch[i]){ b[++cnt].x=q1[a[i][1]]; b[cnt].y=q2[a[i][1]]; for (j=2; j<=l; j++){ b[cnt].x=min(b[cnt].x,q1[a[i][j]]); b[cnt].y=min(b[cnt].y,q2[a[i][j]]); } b[cnt].z=i; } sort(b+1,b+cnt+1,cmp); int ans=0; for (i=1; i<=cnt; i=j+1){ for (j=i; j<cnt && b[j+1].x==b[j].x && b[j+1].y==b[j].y; j++); for (u=i; u<j; u++) if (!mch[b[u].z]) for (v=u+1; v<=j; v++) if (!mch[b[v].z]) if (eql(b[u].z,b[v].z)){ mch[b[u].z]=b[v].z; mch[b[v].z]=b[u].z; ans++; break; } } return ans; } int main(){ srand(20160513); scanf("%d%d%d",&n,&m,&l); n<<=1; int i,j,k,x; char ch=getchar(); while (ch<'!') ch=getchar(); for (i=1; i<=n; i++) for (j=1; j<=l; j++){ x=0; for (k=0; k<4; k++,ch=getchar()) x=(x<<7)+(int)ch; a[i][j]=h.ins(x); } for (i=1; i<=tot; i++) q1[i]=q2[i]=i; x=n>>1; while (x) x-=solve(); for (i=1; i<=n; i++) printf("%d\n",mch[i]); return 0; }
by lych
2016.5.13