首页 > 代码库 > topcoder srm 694 div1 -3

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;    }};

  

topcoder srm 694 div1 -3