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 ...
随机推荐
- Hadoop生态圈-Kafka的本地模式部署
Hadoop生态圈-Kafka的本地模式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Kafka简介 1>.什么是JMS 答:在Java中有一个角消息系统的东西,我 ...
- DNA序列编码中Hairpin的定义和计算
DNA序列编码中Hairpin的定义和计算 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 [1] 张凯. DNA计算核酸编码优化及算法设计[D]. 2008. [2] Shin, ...
- Android利用LocalSocket实现Java端进程与C端进程之间的IPC
Android是建立在Linux之上的OS,在涉及到安全.网络协议.文件加密等功能时,往往需要通过C语言调用底层API来实现,而如何发出指令让C端执行我们想要的功能,并且在执行之后有返回结果呢,这就需 ...
- Ascending Rating(单调队列)
题目描述 Before the start of contest, there are n ICPC contestants waiting in a long queue. They are lab ...
- 【ARTS】01_02_左耳听风-20181119~1125
Algorithm 做一个 leetcode 的算法题 Unique Email Addresses https://leetcode.com/problems/unique-email-addres ...
- Linux下USB suspend/resume源码分析【转】
转自:http://blog.csdn.net/aaronychen/article/details/3928479 Linux下USB suspend/resume源码分析 Author:aaron ...
- tomcat报错:java.net.SocketException: Permission denied["http-nio-80"]
tomcat报错:java.net.SocketException: Permission denied["http-nio-80"] 问题:使用非root账户tomcat启动to ...
- 特性(C# 和 Visual Basic)
特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联. 特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性. 有关更多信息,请参见 反射(C# 和 V ...
- MySql 新建用户与数据库的实际操作步骤
以下的文章主要讲述的是MySql 新建用户的创建.新建数据库的实际操作步骤以及用户如何进行授权和删除用户的实际操作方案.还有对修改密码的实际操作,以下就是正文的主要内容的创建. 1.MySql 新建用 ...
- Heist
CF#509 div2 A 第一次用自己的号打CF祭. 题目描述 昨晚有一家电子商店被抢劫了. 昨天在商店里的所有键盘都是从x开始按升序编号的.例如,如果x=4,并且商店中有3个键盘,那么编号就为4, ...