【做题】TCSRM601 Div1 500 WinterAndSnowmen——按位考虑&dp
原文链接https://www.cnblogs.com/cly-none/p/9695526.html
题意:求有多少对集合\(S,T\)满足:\(S \subseteq \{1,2...n \}, T \subseteq \{1,2...m\},S \bigcap T = \emptyset\),且\(S\)中所有元素的异或和小于\(T\)中所有元素的异或和。对\(10^9+7\)取模。
\(n,m \leq 2000\)
首先,通过记录当前两个集合的异或和,转移时考虑每个元素的3种选择,容易得到\(O(n^3)\)的暴力dp。然而,要对此优化却是一件困难的事情。
但无论如何,对状态的优化的必要的。因此,我们就必须避免同时记录两个集合的异或和。考虑两个异或和如果只有一位,那么它们的大小关系就能通过记录一位来得到。而对于多位的二进制数的大小比较,我们也只用比较不同的最高位就可以了。
因此,我们枚举不同的最高位。那么,我们就可以忽略后面的位,并只用记录我们所枚举的这一位。剩下的问题就在于保证更高的位是相等的。那可以用记录两个数在更高位上的异或和实现,异或和为0,这两个数就是相等的。
时间复杂度\(O(n^2\log n)\)。
upd18.9.25
确实如zhouzhendong所说,这是\(O(n^2)\)的。下面代码已修改。
#include <bits/stdc++.h>
using namespace std;
const int N = 2060, MOD = (int)(1e9 + 7);
int dp[N][N][2],n,m,len,ans;
class WinterAndSnowmen {
public:
int getNumber( int N, int M );
};
int WinterAndSnowmen::getNumber(int N, int M) {
n = N, m = M;
len = max(n,m);
for (int s = 1 ; s <= 12 ; ++ s) {
memset(dp,0,sizeof dp);
dp[0][0][0] = 1;
for (register int i = 1 ; i <= len ; ++ i) {
for (register int j = 0 ; j < (2048 >> (s-1)) ; ++ j) {
for (int k = 0 ; k < 2 ; ++ k) {
if (i <= n)
(dp[i][j^(i>>(s-1))][k] += dp[i-1][j][k]) %= MOD;
if (i <= m)
(dp[i][j^(i>>(s-1))][k ^ ((i >> (s-1))&1)] += dp[i-1][j][k]) %= MOD;
(dp[i][j][k] += dp[i-1][j][k]) %= MOD;
}
}
}
(ans += dp[len][1][1]) %= MOD;
}
return ans;
}
小结:虽然是“思维训练”中的题,但也会有自己没有掌握的技巧。
【做题】TCSRM601 Div1 500 WinterAndSnowmen——按位考虑&dp的更多相关文章
- 【做题】arc078_f-Mole and Abandoned Mine——状压dp
题意:给出一个\(n\)个结点的联通无向图,每条边都有边权.令删去一条边的费用为这条边的边权.求最小的费用以删去某些边使得结点\(1\)至结点\(n\)有且只有一条路径. \(n \leq 15\) ...
- 【做题】spoj4060 A game with probability——dp
赛前做题时忽然发现自己概率博弈类dp很弱,心好慌.(获胜概率或最优解期望) 于是就做了这道题,续了特别久. 一开始列dp式子的时候就花了很长时间,首先搞错了两次,然后忘记了根据上一轮dp值直接确定选什 ...
- bzoj5108 [CodePlus2017]可做题 位运算dp+离散
[CodePlus2017]可做题 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 87 Solved: 63[Submit][Status][Dis ...
- CodeM美团点评编程大赛复赛 做题感悟&题解
[T1] [简要题意] 长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...
- TopCoder SRM502 Div1 500 贪心 01背包
原文链接https://www.cnblogs.com/zhouzhendong/p/SRM502-500.html SRM502 Div1 500 好题. 首先,如果已经确定了解决所有问题的优先级, ...
- SAM 做题笔记(各种技巧,持续更新,SA)
SAM 感性瞎扯. 这里是 SAM 做题笔记. 本来是在一篇随笔里面,然后 Latex 太多加载不过来就分成了两篇. 标 * 的是推荐一做的题目. trick 是我总结的技巧. I. P3804 [模 ...
- C语言程序设计做题笔记之C语言基础知识(下)
C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...
- C语言程序设计做题笔记之C语言基础知识(上)
C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...
- bzoj5108: [CodePlus2017]可做题
Description qmqmqm希望给sublinekelzrip出一道可做题.于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需 要计算其异或前缀和bi,满足条件b1=a1,bi= ...
随机推荐
- JustOj 1036: 习题6.11 迭代法求平方根
题目描述 用迭代法求 .求平方根的迭代公式为: X[n+1]=1/2(X[n]+a/X[n]) 要求前后两次求出的得差的绝对值少于0.00001. 输出保留3位小数 输入 X 输出 X的平方根 样例输 ...
- mycat工作原理
Mycat的原理并不复杂,复杂的是代码,如果代码也不复杂,那么早就成为一个传说了. Mycat的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析: ...
- C++ for循环与迭代器
1.基本的for循环 std::vector<int> arr; ... for(std::vector<int>::iterator it=arr.begin();it!=a ...
- plsql登录报错身份证明检索失败
找到sqlnet.ora文件 在Oracle安装目录下 \product\12.2.0\dbhome_1\network\admin 把 SQLNET.AUTHENTICATION_S ...
- 【Shell循环进程并行处理】利用简单的语句实现for循环并行处理命令
在生信分析中,经常会遇到不同的重复和处理,这样的分析过程有时是非常费时且占用资源并不是很多的,可以同时在后台运行以节约时间,这是并行处理的意义.除了需要并行处理,循环迭代来遍历整个文件夹的需要分析的数 ...
- Javaweb笔记—03(BS及分页的业务流程)
DAO部分:中间层声明该有的变量 pagerBook pageData sumRow sumPage求出总的记录数id唯一标识:select count(id) as rowsum from book ...
- 翻唱 - shape of you - 个个版本
翻唱: http://7j1xky.com1.z0.glb.clouddn.com/1525514286196.mp4 乐队版-我的翻唱-混合 http://7j1xky.com1.z0.glb.cl ...
- PID控制器开发笔记(转)
源: PID控制器开发笔记
- Docker MySQL5.5镜像
定制MySQL的镜像有个很大的难题:mysqld启动之前要初始化数据目录,5.5自带有空账号密码需要初始化. Dockerfile FROM centos # 拷贝需要的安装和MySQL初始脚本 CO ...
- Python查看关键字和帮助信息
1.查看所有的关键字 >>> help('keywords') Here is a list of the Python keywords. Enter any keyword to ...