JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异

87 篇文章 0 订阅

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");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值