题意:

     给你一个串数字,然后让你在这里面挑取两个集合S ,T,集合的要求是

(1)不能为空

(2)S集合的所有元素必须在T集合的左边

(3)S集合的XOR == T集合的AND

     问可以找到多少组这样的集合对。

思路:

      两种方法,一个是枚举T集合的第一个元素,或者是枚举S集合的最后一个元素,首先我们开四个数组


sum_xor[1002][2050] 记录从左到右直到第i个节点的时候的j这个数字有多少种可能

now_xor[1002][2050] 记录从左到右直到第i个节点并且必须选择i这个节点时j出现的次数

sum_and[1002][2050] 同理.(只不过是n-->1)..

now_and[1002][2050] 同理. (只不过是n-->1)..


更新数组的时候可以想象下01背包,当前的状态由上一步的所有可能状态和当前的这个数字组合出来后得到的新状态,对于sum_..记得加上上一步的所有状态,这个题目关键就是枚举的时候不能出现重复的集合对。然后我们枚举一遍就ok了,两种枚举方法,第一种是sum_xor,now_and两个状态组合,另一

个是now_xor ,sum_and组合,给个关键的代码

for(i = 1 ;i <= n ;i ++)

{

    now_xor[i][num[i]] ++;//自己这个状态

    sum_xor[i][num[i]] ++;//自己这个状态

    for(j = 0 ;j <= 2048 ;j ++)

    {

       if(sum_xor[i-1][j])//如果之前有j这个状态

       {

          now_xor[i][j^num[i]] += sum_xor[i-1][j];//新状态的增加值

          sum_xor[i][j^num[i]] += sum_xor[i-1][j];//新状态的增加值

          sum_xor[i][j] += sum_xor[i-1][j];//当前的和也要加上之前的所有可能和

          //然后都MOD一下

        }  

     }

}


AND的同理...


求出来这4个数组之后的两种枚举方法(两种几乎一样)

(1)枚举T集合的第一个

for(i = 2 ;i <= n ;i ++)

{

   for(j = 0 ;j <= 2048 ;j ++)

   if(sum_xor[i-1][j] && now_and[i][j])

   ans = (sum_xor[i-1][j] * now_and[i][j]) % MOD;

}

(2)枚举S集合的最后一位

for(i = 1 ;i <= n - 1 ;i ++)

{

   for(j = 0 ;j <= 2048 ;j ++)

   if(now_xor[i-1][j] && sum_and[i][j])

   ans = (now_xor[i-1][j] * sum_and[i][j]) % MOD;

}



#include<stdio.h>
#include<string.h> #define MOD (1000000000 + 7)

__int64
sum_xor[1002][2050] ,now_xor[1002][2050];
__int64
sum_and[1002][2050] ,now_and[1002][2050];
__int64
num[1002]; int main ()
{
int
i ,j ,n ,t;
scanf("%d" ,&t);
while(
t--)
{

scanf("%d" ,&n);
for(
i = 1 ;i <= n ;i ++)
scanf("%I64d" ,&num[i]);
memset(sum_xor ,0 ,sizeof(sum_xor));
memset(now_xor ,0 ,sizeof(now_xor));
for(
i = 1 ;i <= n ;i ++)
{

sum_xor[i][num[i]] ++;
now_xor[i][num[i]] ++;
for(
j = 0 ;j <= 2048 ;j ++)
if(
sum_xor[i-1][j])
{

now_xor[i][j^num[i]] += sum_xor[i-1][j];
sum_xor[i][j^num[i]] += sum_xor[i-1][j];
sum_xor[i][j] += sum_xor[i-1][j];
now_xor[i][j^num[i]] %= MOD;
sum_xor[i][j^num[i]] %= MOD;
sum_xor[i][j] %= MOD;
}
}

memset(sum_and ,0 ,sizeof(sum_and));
memset(now_and ,0 ,sizeof(now_and));
for(
i = n ;i >= 1 ;i --)
{

sum_and[i][num[i]] ++;
now_and[i][num[i]] ++;
for(
j = 0 ;j <= 2048 ;j ++)
if(
sum_and[i+1][j])
{

now_and[i][j&num[i]] += sum_and[i+1][j];
sum_and[i][j&num[i]] += sum_and[i+1][j];
sum_and[i][j] += sum_and[i+1][j];
now_and[i][j&num[i]] %= MOD;
sum_and[i][j&num[i]] %= MOD;
sum_and[i][j] %= MOD;
}
}
__int64
ans = 0;
for(
i = 2 ;i <= n ;i ++)
{
for(
j = 0 ;j <= 2048 ;j ++)
if(
sum_xor[i-1][j] && now_and[i][j])
ans = (ans + sum_xor[i-1][j] * now_and[i][j]) % MOD;
}

printf("%I64d\n" ,ans);
}
return
0;
}


hdu4901 枚举状态(找集合对S(xor) ==T(and))的更多相关文章

  1. { MySQL基础数据类型}一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型

    MySQL基础数据类型 阅读目录 一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型 一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己 ...

  2. 1315E Double Elimination DP 01枚举状态和倍增思想

    E. Double Elimination DP 01枚举状态和倍增思想 题意 参考DOTA2双败赛制,一共有\(2^n\)个队打n轮 其中你有k喜欢的队伍,由你掌控比赛的输赢请问比赛中包含你喜欢的队 ...

  3. 6-12 varchar和char 枚举类型enum 集合set

    1       字符类型char和varchar #官网:https://dev.mysql.com/doc/refman/5.7/en/char.html #注意:char和varchar括号内的参 ...

  4. Mysql数据类型《三》枚举类型与集合类型

    枚举类型与集合类型 字段的值只能在给定范围中选择,如单选框,多选框 enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female set 多选 在给定的范围内可以选择一个或一 ...

  5. mysql枚举类型与集合类型

    枚举类型与集合类型 字段的值只能在给定范围中选择,如单选框,多选框 enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female set 多选 在给定的范围内可以选择一个或一 ...

  6. 【POJ 2411】【Mondriaans Dream】 状压dp+dfs枚举状态

    题意: 给你一个高为h,宽为w的矩阵,你需要用1*2或者2*1的矩阵填充它 问你能有多少种填充方式 题解: 如果一个1*2的矩形横着放,那么两个位置都用二进制1来表示,如果是竖着放,那么会对下一层造成 ...

  7. Delphi基本类型--枚举 子界 集合 数组

    [plain] view plain copy <strong>根据枚举定义集合 </strong> TMyColor = (mcBlue, mcRed); TMyColorS ...

  8. Http状态码集合

    忘了之前在哪里收集的了,先表示感谢. 状态码 含义 100 客户端应当继续发送请求.这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝.客户端应当继续发送请求的剩余部分,或者如果请 ...

  9. HDU 5025Saving Tang Monk BFS + 二进制枚举状态

    3A的题目,第一次TLE,是因为一次BFS起点到终点状态太多爆掉了时间. 第二次WA,是因为没有枚举蛇的状态. 解体思路: 因为蛇的数目是小于5只的,那就首先枚举是否杀死每只蛇即可. 然后多次BFS, ...

随机推荐

  1. 剑指 Offer 31. 栈的压入、弹出序列 + 入栈顺序和出栈顺序的匹配问题

    剑指 Offer 31. 栈的压入.弹出序列 Offer_31 题目详情: 解析: 这里需要使用一个栈来模仿入栈操作. package com.walegarrett.offer; /** * @Au ...

  2. Java基础 随笔整理

    Java基础随笔整理 为了方便阅读,特整理了相关的学习笔记 Java感想 操千曲而后晓声 Java入门 Java其他 Java虚拟机详解 语言入门百题 Java开发工具 · Eclipse Java语 ...

  3. 翻译:《实用的Python编程》04_00_Overview

    目录 | 上一节 (3 程序组织) | 下一节 (5 Python对象的内部工作原理) 4. 类和对象 到目前为止,我们的程序仅使用了内置的 Python 数据类型.本节,我们介绍类(class)和对 ...

  4. 华为OD机试题

    """最长回文字符串问题"""# 说明:方法很多,这个是最简单,也是最容易理解的一个,利用了动态规化.# 先确定回文串的右边界i,然后以右边 ...

  5. External Libraries中没有Maven的jar包的原因(已解决)

    **深坑!** ## External Libraries中没有Maven的jar包的原因(已解决) 2021年3月1日 --- 搭建一个新项目 IDEA 从 Git 上拉 拉去Maven项目然后 m ...

  6. 一键安装KMS服务

    本文转载于 秋水逸冰 » 一键安装 KMS 服务脚本 KMS,是 Key Management System 的缩写,也就是密钥管理系统.这里所说的 KMS,毋庸置疑就是用来激活 VOL 版本的 Wi ...

  7. PTA 中序输出度为1的结点

    6-9 中序输出度为1的结点 (10 分)   本题要求实现一个函数,按照中序遍历的顺序输出给定二叉树中度为1的结点. 函数接口定义: void InorderPrintNodes( BiTree T ...

  8. Java学习之数组的简单用法

    •概念 其实所谓的数组指的就是一组相关类型的变量集合,并且这些变量可以按照统一的方式进行操作. 数组本身属于引用数据类型,那么既然是引用数据类型,这里面实际又会牵扯到内存分配: 而数组的定义语法有两种 ...

  9. OO第一单元感悟与体会

    第一单元的三次编程作业结束了,现在分享一些我对自己作业的分析和感想 1.程序结构的分析 第一次作业: 本次作业我的主要思路是,为每一项写一个正则表达式,在输入的字符串中匹配每一项,多项式类中保存着一个 ...

  10. APP | edxposed框架+trustmealredy模块抓包小程序

    出品|MS08067实验室(www.ms08067.com) 本文作者:ketchup(Ms08067实验室 SRSP TEAM小组成员) 一.下载edxposed框架,由于安卓5.0版本以下的不支持 ...