• [JZOJ100047] 【NOIP2017提高A组模拟7.14】基因变异


    Description

    21 世纪是生物学的世纪,以遗传与进化为代表的现代生物理论越来越多的 进入了我们的视野。 如同大家所熟知的,基因是遗传因子,它记录了生命的基本构造和性能。 因此生物进化与基因的变异息息相关,考察基因变异的途径对研究生物学有着 至关重要的作用。现在,让我们来看这样一个模型:
    1、所有的基因都可以看作一个整数或该整数对应的二进制码;
    2、在 1 单位时间内,基因 x 可能会在其某一个二进制位上发生反转;
    3、在 1 单位时间内,基因 x 可能会遭到可感染基因库内任一基因 y 的影响 而突变为 x XOR y。
    现在给出可感染基因库,Q 组询问,每组给出初始基因与终止基因,请你 分别计算出每种变异最少要花费多少个单位时间。
     

    Input

    第 1 行两个整数 N, Q; 第 2 行 N 个用空格隔开的整数分别表示可感染基因库内的基因; 接下来 Q 行每行两个整数 S、T,分别表示初始基因与终止基因。

    Output

    输出 Q 行,依次表示每组初始基因到终止基因间最少所花时间。

    Sample Input

    3 3 
    1 2 3 
    3 4 
    1 2 
    3 9

    Sample Output

    2 
    1
    2

    Data Constraint

    对于 20%的数据,N = 0;
    对于额外 40%的数据,1 ≤ Q ≤ 100,所有基因表示为不超过 10^4 的非负整 数;
    对于 100%的数据,0 ≤ N ≤ 20,1 ≤ Q ≤ 10^5,所有基因表示为不超过 10^6 的 非负整数。 

    其实所有的操作都可以看成一个数亦或另一个数(显然)。

    那么 :  st ^ x1 ^ x2 ^ ... ^ xk = ed ,

    两边同时异或$large st$得到

     x1 ^ x2 ^ ... ^ xk = ed ^ st。

    所以我们只需要求出0变成st^ed的步数就行了。

    考虑到n很小,1e6也最多是$large 2^{20}$。

    所以直接bfs一遍就可以每次$large O(1)$求出答案。


    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <ctime>
    using namespace std;
    #define reg register 
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    
    int n, Q;
    int a[25];
    int dis[10000005];
    bool vis[10000005];
    
    int main()
    {
    //    double ST = clock();
        n = read(), Q = read();
        for (reg int i = 1 ; i <= n ; i ++) a[i] = read();
        queue <int> q;
        q.push(0);
        vis[0] = 1;
        while(!q.empty())
        {
            int x = q.front();q.pop();
            for (reg int i = 1 ; i <= n ; i ++)
            {
                int t = x ^ a[i];
                if (t > 3000000) continue;
                if (vis[t]) continue;
                vis[t] = 1;
                dis[t] = dis[x] + 1;
                q.push(t);
            }
            for (reg int i = 1 ; i <= 25 ; i ++)
            {
                int t = x;
                int mark = (1 << i - 1);
                t ^= mark;
                if (t > 3000000) continue;
                if (vis[t]) continue;
                vis[t] = 1;
                dis[t] = dis[x] + 1;
                q.push(t);
            }
        }
        while(Q--) {
            int st = read(), ed = read();
            printf("%d
    ", dis[st ^ ed]);
        }
    //    double ED = clock();
    //    printf("%.0lfms
    ", ED - ST);
        return 0;
    }
  • 相关阅读:
    Yii2框架bootstrap样式理解
    spring 配置bean的方法及依赖注入发方式
    C#深拷贝
    【麦子学院】Linux cmd命令大全
    JEECG中的validform验证ajaxurl的使用方法
    ORACLE 如何查询被锁定表及如何解锁释放session
    获取请求真实ip
    jsp值传到后台Struts2中的action三种方法
    ajax 二级联动与springmvc 交互
    SpringMVC返回json数据的三种方式
  • 原文地址:https://www.cnblogs.com/BriMon/p/9578553.html
Copyright © 2020-2023  润新知