topcoder srm 694 div1 -3

1、给出$n$个数字,将其分成三个非空的组,每组的权值为该组所有数字的抑或。选择一种分法使得三组的权值和最大?

思路:记录前两组的权值且三组有没有数字时第三组的值。(当前两组的值知道时第三组的权值是确定的,因为三组的抑或值是确定的)

#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <set>
#include <vector>
#include <time.h>
#include <queue>
#include <stack>
#include <map>
#include <assert.h>
using namespace std;



int f[2][256][256][8];


class TrySail
{
public:
    int get(vector<int> A)
    {
        int pre=0,cur=1;
        memset(f[pre],-1,sizeof(f[pre]));
        f[0][0][0][0]=0;
        for(int i=0;i<(int)A.size();++i)
        {
            memset(f[cur],-1,sizeof(f[cur]));
            const int w=A[i];
            for(int b=0;b<256;++b) {
                for(int c=0;c<256;++c) {
                    for(int d=0;d<8;++d) {
                        int k=f[pre][b][c][d];
                        if(k==-1) continue;
                        f[cur][b^w][c][d|4]=k;
                        f[cur][b][c^w][d|2]=k;
                        f[cur][b][c][d|1]=k^w;
                    }
                }
            }
            pre^=1;
            cur^=1;
        }
        int ans=0;
        for(int a=0;a<256;++a) {
            for(int b=0;b<256;++b) {
                if(f[pre][a][b][7]!=-1) {
                    ans=max(ans,f[pre][a][b][7]+a+b);
                }
            }
        }
        return ans;
    }
};

  

2、给出$n*m$的只包含'A'到'Z'的字符矩阵。对于一个列的集合$S$,如果任意两行$i,j$在$S$上不完全相同,称$S$可以区分所有行。问有多少种列的子集可以区分所有行?$n\leq 1000,m\leq 20$

思路:首先,找到哪些列的子集不能区分所有行。令$f[s]=1$表示集合$s$不能区分所有行,那么所有的$s$^$2^{k}$都不能区分。其中$k$满足$s$&$2^{k}\neq 0$。

#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <set>
#include <vector>
#include <time.h>
#include <queue>
#include <stack>
#include <map>
#include <assert.h>
using namespace std;


int f[1<<20];

class DistinguishableSetDiv1
{

public:
    int count(vector<string> A)
    {

        int n=A.size();
        int m=A[0].size();

        memset(f,0,sizeof(f));
        for(int i=0;i<n;++i) for(int j=i+1;j<n;++j)
        {
            int s=0;
            for(int k=0;k<m;++k) if(A[i][k]==A[j][k]) s|=1<<k;
            f[s]=1;
        }
        int ans=0;
        for(int i=(1<<m)-1;i>=0;--i)
        {
            if(f[i])
            {
                for(int k=0;k<m;++k) if(i&(1<<k)) f[i^(1<<k)]=1;
            }
            else ++ans;
        }
        return ans;
    }
};

  

posted @ 2017-05-22 10:35  朝拜明天19891101  阅读(458)  评论(0编辑  收藏  举报