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 ...
随机推荐
- Saltstack-API(十二)
Saltstack-API 官方文档 https://docs.saltstack.com/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.htm ...
- idea2017破解方法
破解方法 切换license server然后 输入网址:http://idea.iteblog.com/key.php即可
- C#_界面程序_数码游戏
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- spring框架学习(一)入门
spring 入门--IOC 1.导入jar包 4 + 1 : 4个核心(beans.core.context.expression) + 1个依赖(commons-loggins...jar) ...
- es6笔记(4) Set数据结构
概要 介绍: 集合是由一组无序且唯一的项组成的,这个数据结构使用了与有限集合相同的数学概念,应用在计算机的数据结构中. ES6提供了数据结构Set.它类似于数组,但是没有重复的值. 特点: key与v ...
- 第11月第3天 直播 rtmp yuv
1. LiveVideoCoreSDK AudioUnitRender ==> MicSource::inputCallback ==> GenericAudioMixer::pushBu ...
- SqlMapConfig.xml全局配置文件介绍——(四)
----------mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:----------- properties(属性) settings(全局配置参数) typeAlia ...
- 【前端node开发】你需要的Express开发教程
1.极简Node教程-七天从小白变大神(一:你需要Express) https://www.jianshu.com/p/b4701a6efc50
- python基础-列表元组字典
1.列表和元组 列表可以对数据实现最方便的存储.修改等操作 names=["Alex","tenglan","Eric","Rai ...
- android上使用蓝牙设备进行语音输入
主要实现步骤如下:1.确保已经和蓝牙耳机配对连接上.2.开启蓝牙信道AudioManager mAudioManager = (AudioManager)getSystemService(Contex ...