HDU3693 Math Teacher's Homework ---- 数位DP
HDU3693 Math Teacher's Homework
一句话题意
给定$n, k以及m_1, m_2, m_3, ..., m_n$求$x_1 \oplus x_2 \oplus x_3 \oplus ... \oplus x_n == K(x_1 \leq m_1, x_2 \leq m_2...)$ 的方案数。
题解
一开始口糊了一下,然后写代码的时候发现不少东西没考虑周到,于是就看起了题解。
我们首先需要发现一个重要的性质:
如果某一位上不受m限制(也就是选0或选1都可以)那么无论其它数的这一位位选什么都可以通过这一位来变成结果和K的这一位相等
为了避免来自$x <= m$的麻烦,我们首先让$m ++$, 使条件变为$x < m$。
然后按照数位dp的套路对位分析。
首先假设我们处理到了第j位,然后从高位到$j + 1$位都已经到了最大值
然后第$j$位由于要小于m,所以m的这一位必然1,然后j的这一位必然是0
然后按照套路我们发现如果这一位我们选了0,那么后面的位随便选都不会大于m
为了方便dp,我们令每一位最早允许随便选的那个$x_i$为$A_j$,这个数将在后面被限制以使其它自由位达到K上对应位的要求
我们记第j位上的第i个数字为自由的,当且仅当这个位不是被m限制了(即第i个数从高位枚举到第一个比m小的位置),且不是那些被最早选择(上一行的定义)限制的数字。
然后每一位上的方案数就是$2^{自由数个数-1}$
于是我们设$dp[i][j][0/1]$表示第i个数的“第i个数从高位枚举到第一个比m小的位置”为j,此位的异或值为0/1
下面我们记
$num[i][j]$为第i个数字第j位
$sum[i][j]$为j位上从第一个数字异或到第i个数字的结果
然后分情况(自由数位置)讨论从状态$dp[i - 1][k][r]$(注意大小写)(注意下面$2^x$的下标)转移,若
m此位可以有不同限制,即$num[i][j] == 1$
$j < k$:$dp[i][j][sum[i - 1][j]] += dp[i - 1][k][r] * 2^k$
$j > k$:$dp[i][k][r \oplus sum[i - 1][j]] += dp[i - 1][k][r] * 2^j$
$j == k$:$dp[i][j][r] += dp[i - 1][k][r] * 2^k$
最后要求$k[j] == sum[n][j]$的时候才能统计入答案
(然而我并不知道怎么用Latex打出'^' ......)
代码如下:
#include <cstdio> #include <bitset>
#include <cstring> using namespace std; char buf[], *pc = buf; inline void Main_Init(){
static bool inited = false;
if(inited) fclose(stdin), fclose(stdout);
else {
fread(buf, , , stdin);
inited = true;
}
} inline int read(){
int num = ;
char c;
while((c = *pc ++) < );
while(num = num * + c - , (c = *pc ++) >= );
return num;
} //Source Code const int MAXN = ;
const int MAXM = ;
const int MODS = ; int n, ans;
int x[MAXN];
unsigned int bin[MAXM];
int dp[MAXN][MAXM][]; bitset<> K, num[MAXN], sum[MAXN]; int main(){
Main_Init();
for(int i = ; i < ; i++) bin[i] = << i;
while(n = read(), n){
K = read();
for(int i = ; i <= n; i++)
num[i] = x[i] = read() + ;
memset(sum, , sizeof(sum)), memset(dp, , sizeof(dp));
ans = ;
dp[][][] = ;
for(int j = ; j < ; j++) sum[][j] = num[][j];
for(int i = ; i <= n; i++)
for(int j = ; j < ; j++)
sum[i][j] = sum[i - ][j] ^ num[i][j];
for(int i = ; i <= n; i++){
for(int j = ; j < ; j++){
if(!num[i][j]) continue;
for(int k = ; k < ; k++){
for(int r = ; r < ; r++){
if(dp[i - ][k][r]){
if(j > k) dp[i][j][sum[i - ][j]] = (dp[i][j][sum[i - ][j]] + 1ll * dp[i - ][k][r] * bin[k]) % MODS;
else if(j < k) dp[i][k][r ^ num[i][k]] = (dp[i][k][r ^ num[i][k]] + 1ll * dp[i - ][k][r] * bin[j]) % MODS;
else dp[i][j][r] = (dp[i][j][r] + 1ll * dp[i - ][k][r] * bin[k]) % MODS;
}
}
}
}
}
for(int i = ; i >= && K[i + ] == sum[n][i + ]; i--)
ans = (1ll * ans + dp[n][i][K[i]]) % MODS;
printf("%d\n", ans);
}
Main_Init();
return ;
}
HDU3693 Math Teacher's Homework ---- 数位DP的更多相关文章
- Math teacher's homework
Title:[Math teacher's homework] Description 题目大意:给你n个数m1,m2...mn,求满足X1 xor X2 xor ... xor Xn=k,0< ...
- POJ 3986 Math teacher's homework
题目 给出\(n,m_1,m_2,...,m_n\),求\(x_1 xor x_2 xor ... xor x_n=k (0 \leq x_i \leq m_i)\)的解的数量.二进制位数小于\(32 ...
- 题解 Math teacher's homework
题目传送门 题目大意 给出 \(n,k\) 以及 \(a_{1,2,...,n}\) ,求有多少个 \(m_{1,2,...,n}\) 满足 \(\forall i,m_i\le a_i\) 且 \( ...
- hiho1259 A Math Problem (数位dp)
题目链接:http://hihocoder.com/problemset/problem/1259 题目大意:g(t)=(f(i)%k=t)的f(i)的个数 求所有的(0-k-1)的g(i)的异或总值 ...
- 2018.09.28 hdu5435A serious math problem(数位dp)
传送门 数位dp卡常题. 写了一发dfs版本的发现过不了233. 于是赶紧转循环版本. 预处理出f数组. f[i][j]f[i][j]f[i][j]表示前i位数异或和为j的方案数. 然后每次直接数位d ...
- HDU 4507 (鬼畜级别的数位DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题目大意:求指定范围内与7不沾边的所有数的平方和.结果要mod 10^9+7(鬼畜の元凶) 解题 ...
- HDU 2089 数位dp入门
开始学习数位dp...一道昨天看过代码思想的题今天打了近两个小时..最后还是看了别人的代码找bug...(丢丢) 传说院赛要取消 ? ... 这么菜不出去丢人也好吧~ #include<stdi ...
- hdu5787(数位dp)
基础的数位dp,才发现今天才终于彻底搞懂了数位dp... // // main.cpp // hdu5787.1 // // Created by New_Life on 16/8/10. // Co ...
- [kuangbin带你飞]专题十五 数位DP
ID Origin Title 62 / 175 Problem A CodeForces 55D Beautiful numbers 30 / 84 Problem B HD ...
随机推荐
- Java基础-使用JAVA代码剖析MD5算法实现过程
Java基础-使用JAVA代码剖析MD5算法实现过程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- bzoj千题计划284:bzoj2882: 工艺
http://www.lydsy.com/JudgeOnline/problem.php?id=2882 将串S复制一遍变成SS 对SS构建后缀自动机,在上面走标号最小的边len(S)步,即可得最小循 ...
- Spring RedisTemplate操作-哈希操作(3)
@Autowired @Resource(name="redisTemplate") private RedisTemplate<String, String> rt; ...
- [iOS]深拷贝/浅拷贝区别
来点鸡汤: // 所谓拷贝 就是在原有的对象的基础上产生一个新的副本对象.有两点原则: // 1. 改变原对象的属性和行为不会影响副本对象 // 2. 改变副本对象的属性和行为不会影响原对象 ...
- G. (Zero XOR Subset)-less(线性基)
题目链接:http://codeforces.com/contest/1101/problem/G 题目大意:给你n个数,然后让你把这n个数分成尽可能多的集合,要求,每个集合的值看做这个集合所有元素的 ...
- Linux 内核中断内幕【转】
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/ 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器.中断分类 ...
- shell脚本练习【转】
1.写一个脚本,判断当前系统上所有用户的shell是否为可登录shell(即用户的shell不是/sbin/nologin):分别这两类用户的个数:通过字符串比较来实现: #脚本内容 [root@ce ...
- VMware下centos桥接模式静态ip配置
声明:本文转载自http://blog.csdn.net/ltr15036900300/article/details/48828207,非原创. 一.配置虚拟机centos网络 备份网络文件 [ro ...
- JavaEE 学习框架
JavaSE JavaWeb基础 ssh+hibernate+spring ssm+spring+mybatis 项目1 电商项目(项目二)
- python3.6连接oracle数据库
下载cx_Oracle模块模块: https://pypi.python.org/pypi/cx_Oracle/5.2.1#downloads 这里下载的是源码进行安装 [root@oracle or ...