zoukankan      html  css  js  c++  java
  • BAPC2014 K&&HUNNU11591:Key to Knowledge(中途相遇法)

    题意:

    有N个学生。有M题目

    然后相应N行分别有一个二进制和一个整数

    二进制代表该同学给出的每道题的答案。整数代表该同学的答案与标准答案相符的个数

    要求推断标准答案有几个,假设标准答案仅仅有一种。则输出标准答案


    思路:

    非常easy想到状态压缩。可是非常明显1<<30纯粹的状压是会超时的,那么我们能够优化一半,变成1<<15

    也就是说,对于一个串,我们分半处理

    首先处理前一半,讨论前一半与标准答案相符的状况。然后再讨论后半串,看与标准答案相符的情况能不能与前一半相匹配,从而算出答案


    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    using namespace std;
    
    #define ls 2*i
    #define rs 2*i+1
    #define UP(i,x,y) for(i=x;i<=y;i++)
    #define DOWN(i,x,y) for(i=x;i>=y;i--)
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define W(a) while(a)
    #define gcd(a,b) __gcd(a,b)
    #define LL long long
    #define ULL unsigned long long
    #define N 100005
    #define INF 0x3f3f3f3f
    #define EXP 1e-8
    #define rank rank1
    const int mod = 1000000007;
    
    int t,n,m;
    char str[50][50];
    int a[50];
    LL num[50][2];
    int hsh[1<<16]= {0};
    
    int main()
    {
        int i,j,k;
        for(i = 0; i<(1<<16); i++)//hsh记录1的个数
        {
            t = i;
            while(t)
            {
                hsh[i]+=t%2;
                t/=2;
            }
        }
        scanf("%d",&t);
        while(t--)
        {
            LL ans = 0;
            map<LL,int> cnt;
            map<LL,int> state;
            scanf("%d%d",&n,&m);
            for(i = 0; i<n; i++)
            {
                scanf("%s%d",str[i],&a[i]);
                num[i][0]=num[i][1] = 0;
                for(j = 0; j<m/2; j++)//记录前一半的2进制状态
                    num[i][0] = num[i][0]*2+(str[i][j]-'0');
                for(j = m/2; j<m; j++)//记录后一半的2进制状态
                    num[i][1] = num[i][1]*2+(str[i][j]-'0');
            }
            //前半部的处理
            int s = m/2;
            for(i = 0; i<(1<<s); i++)
            {
                LL tem = 0;
                for(j = 0; j<n; j++)
                {
                    k = hsh[i^num[j][0]];//与答案不同样的个数
                    if(s-k>a[j]) break;
                    tem = tem*30+s-k;//30进制存状态
                }
                if(j==n)
                {
                    cnt[tem]++;//该状态有几种
                    state[tem] = i;
                }
            }
            s = m-s;//后一半
            int s1,s2;
            for(i = 0; i<(1<<s); i++)
            {
                LL tem = 0;
                for(j = 0; j<n; j++)
                {
                    k = hsh[i^num[j][1]];
                    if(s-k>a[j]) break;
                    tem = tem*30+a[j]-(s-k);//找回前一半的状态
                }
                if(j==n&&cnt[tem])
                {
                    ans+=cnt[tem];
                    s1 = state[tem];
                    s2 = i;
                }
            }
            if(ans==1)
            {
                stack<int> Q;
                for(i = 0; i<s; i++)
                {
                    Q.push(s2%2);
                    s2/=2;
                }
                for(i = 0; i<m-s; i++)
                {
                    Q.push(s1%2);
                    s1/=2;
                }
                while(!Q.empty())
                {
                    printf("%d",Q.top());
                    Q.pop();
                }
                printf("
    ");
            }
            else
                printf("%d solutions
    ",ans);
        }
    
        return 0;
    }
    


  • 相关阅读:
    -bash: fork: Cannot allocate memory 问题的处理
    Docker top 命令
    docker常见问题修复方法
    The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
    What's the difference between encoding and charset?
    hexcode of é î Latin-1 Supplement
    炉石Advanced rulebook
    炉石bug反馈
    Sidecar pattern
    SQL JOIN
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6924480.html
Copyright © 2011-2022 走看看