Description
21 世纪是生物学的世纪,以遗传与进化为代表的现代生物理论越来越多的 进入了我们的视野。 如同大家所熟知的,基因是遗传因子,它记录了生命的基本构造和性能。 因此生物进化与基因的变异息息相关,考察基因变异的途径对研究生物学有着 至关重要的作用。现在,让我们来看这样一个模型:
1、所有的基因都可以看作一个整数或该整数对应的二进制码;
2、在 1 单位时间内,基因 x 可能会在其某一个二进制位上发生反转;
3、在 1 单位时间内,基因 x 可能会遭到可感染基因库内任一基因 y 的影响 而突变为 x XOR y。
现在给出可感染基因库,Q 组询问,每组给出初始基因与终止基因,请你 分别计算出每种变异最少要花费多少个单位时间。
分析
我们看到第二条,在其某一个二进制位上发生反转,这个等同于这个数异或2的次幂。
现在就将两种变异方式统一了,异或一个数。
对于每一个询问,
初始基因s一定是异或了一些数之后变为了终止基因t。
即s xor
a1
xor
a2
xor …xor
an
=t
异或运算满足乘法运算的规律
也就说 s xor t=
a1
xor
a2
xor …xor
an
s xor t 我们是知道的,现在我们就需要求出用最少个数的
ai
异或出来的结果=s xor t
很容易就想到了dp,此外还有一种别的方法,就是bfs,这个比dp更快。
code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define N 1048575
using namespace std;
int n,a[43],f[N],g[N],m,x,y;
char ch;
void read(int &n)
{
n=0;
ch=getchar();
while((ch<'0' || ch>'9') && ch!='-')ch=getchar();
int w=1;
if(ch=='-')w=-1,ch=getchar();
while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=getchar();
n*=w;
}
void write(int x)
{
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main()
{
read(n);read(m);
for(int i=1;i<=n;i++)
read(a[i]);
a[n+1]=1;
for(int i=n+2;i<=n+20;i++)
a[i]=a[i-1]*2;
memset(f,127,sizeof(f));
memset(g,127,sizeof(g));
for(int i=1;i<=n+20;i++)
{
f[a[i]]=1;
for(long long j=0;j<N;j++)
if(g[j]<100)
{
if((j^a[i])<N)f[j^a[i]]=min(f[j^a[i]],g[j]+1);
}
for(int j=0;j<N;j++)
g[j]=min(f[j],g[j]);
}
f[0]=g[0]=0;
for(int i=1;i<=m;i++)
{
read(x);read(y);
write(g[x^y]);
printf("\n");
}
}