hdu 4025 Equation of XOR 状态压缩
思路:
设: 方程为
1*x1 ^ 1*x2 ^ 0*x3 = 0;
0*x1 ^ 1*x2 ^ 1*x3 = 0;
1*x1 ^ 0*x2 ^ 0*x3 = 0
把每一列压缩成一个64位整数,因为x范围为 (0 1 2 3) 二进制位不超过2, 方程组行数不超过30 则用一个大于60位整数就能表示每一列的状态,然后枚举各列就可以了。
如上面方程组
第一列为 1 0 1 ,可写为a1 = 11 00 11, 假设x1取2, 则第一列 s1 = 10 10 10, s1&a1 = 10 00 10 即为第一列的状态
第二列 a2 = 11 11 00 设x2 = 1 则 s2 = 01 01 01, 第二列状态为 a2&s2 = 01 01 00
第三列 a3 = 00 11 00 设x3 = 3 则 s3 = 11 11 11, 第三列状态为 a3&s3 = 00 11 00
对每列状态异或 (a1&s1) ^ (a2&s2) ^ (a3&s3) = 11 10 10 显然 x1=2 x2=1 x3=3 不是方程组的解
代码如下:
1 #include<cstdio> 2 #include<map> 3 #include<cstring> 4 #define ll __int64 5 using namespace std; 6 ll a[23],x[23][5],ans; 7 map<ll,ll>p; 8 void dfs(int d,int n,ll res,ll f) 9 { 10 if(d==n){ 11 if(f) p[res]++; 12 else if(p[res]) ans+=p[res]; 13 return ; 14 } 15 for(int i=1;i<=x[d][0];i++){ 16 ll temp=x[d][i]&a[d]; 17 dfs(d+1,n,temp^res,f); 18 } 19 } 20 int main() 21 { 22 int t,i,j,n,m,k; 23 ll temp=3,te; 24 scanf("%d",&t); 25 while(t--){ 26 scanf("%d%d",&n,&m); 27 memset(a,0,sizeof(a)); 28 memset(x,0,sizeof(x)); 29 p.clear(); 30 for(i=0;i<n;i++) 31 for(j=0;j<m;j++){ 32 scanf("%I64d",&te); 33 if(te) 34 a[j]|=(temp<<(2*i)); 35 } 36 for(i=0;i<m;i++){ 37 scanf("%d",&x[i][0]); 38 for(j=1;j<=x[i][0];j++){ 39 scanf("%I64d",&te); 40 x[i][j]=te; 41 for(k=1;k<n;k++){ 42 x[i][j]|=(te<<(2*k)); 43 } 44 } 45 } 46 ans=0; 47 dfs(0,m/2,0,1); 48 dfs(m/2,m,0,0); 49 printf("%I64d\n",ans); 50 } 51 return 0; 52 }