很久以前做过的一道数位DP,现在用一种新的解决数位DP的比较一般的方法。

数位DP裸题是:求[L,R]有多少个数。

先转化成求[0,R]有多少个数,然后区间相减即可。

对于[0,R]中的所有数,用0补齐前面的空位,使得每个数的长度都为R的长度。

状态:

dp[pos][0]表示从最高位到pos位,没有顶上界的数的个数

dp[pos][1]表示从最高位到pos位,顶到上界的数的个数(好吧,这个问题中,它一定为1)

然后考虑转移,

dp[pos][0]->dp[pos-1][0](通过枚举pos-1位的数进行转移)

dp[pos][1]->dp[pos-1][0](通过枚举pos-1位,小于该位上界的数进行转移)

dp[pos][1]->dp[pos-1][1](只能在pos-1位填1)

顺推倒推都可以。

dp[1][0]+dp[1][1]就是答案。

对于其它的数位DP,都可以在这个DP上加上需要的状态维,然后解决其它问题。

上面的dp[pos][1]看似没有用(因为始终为1),但是实际上,我们是必须要它的,比如这道题。

我们设dp[pos][top][tail]表示:“比pos高的位,顶上界(top为1)或不顶上界(top为0),最后一位为tail的数的个数(并且要求这个数不为0)“

然后自己YY转移吧(这个不为0的要求和上一道题有点不同,具体看代码)。

新方法:

 /**************************************************************
Problem: 1026
User: idy002
Language: C++
Result: Accepted
Time:0 ms
Memory:808 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#define abs(a) ((a)>0?(a):-(a)) typedef long long poi; poi lf, rg;
int aa[], tot;
poi dp[][][]; poi calc( poi v ) { // v in [1,oo)
for( tot=; v; v/= )
aa[++tot]=v%;
memset( dp, , sizeof(dp) );
dp[tot][][aa[tot]] = ;
for( int i=; i<aa[tot]; i++ )
dp[tot][][i] = ;
for( int i=tot; i>=; i-- ) {
for( int c=; c<=; c++ )
for( int s=; s<=; s++ )
if( abs(s-c)>= )
dp[i-][][s] += dp[i][][c];
for( int s=; s<=; s++ )
dp[i-][][s]++;
for( int s=; s<aa[i-]; s++ )
if( abs(s-aa[i])>= )
dp[i-][][s] += dp[i][][aa[i]];
dp[i-][][aa[i-]] = dp[i][][aa[i]] && abs(aa[i]-aa[i-])>=;
}
poi rt=dp[][][aa[]];
for( int i=; i<=; i++ )
rt += dp[][][i];
return rt;
}
int main() {
scanf( "%lld%lld", &lf, &rg );
printf( "%lld\n", calc(rg)-(lf==?:calc(lf-)) );
}

以前的:

 /**************************************************************
Problem: 1026
User: idy002
Language: C++
Result: Accepted
Time:0 ms
Memory:804 kb
****************************************************************/ #include <cstdio>
#include <algorithm>
using namespace std; struct Form {
int n;
int b[];
int src;
Form( int a ) {
n = ;
src = a;
if( a== ) {
n=;
b[] = ;
return;
}
while( a ) {
b[++n] = a%;
a/=;
}
}
};
int dp[][]; // dp[0~9][0~10] void init() {
for( int h=; h<=; h++ )
dp[h][] = ;
for( int l=; l<=; l++ )
for( int h=; h<=; h++ )
for( int g=; g<=; g++ )
if( abs(g-h)>= )
dp[h][l] += dp[g][l-];
} int calc( const Form &fm) { // [0,fm.src)
int ans = fm.src!=; //
for( int l=; l<fm.n; l++ )
for( int h=; h<=; h++ ) {
ans += dp[h][l];
//printf( "(h=%d,l=%d)\n", h, l );
}
for( int h=; h<fm.b[fm.n]; h++ ) {
ans += dp[h][fm.n];
//printf( "(h=%d,l=%d)\n", h, fm.n );
}
for( int l=fm.n-; l>=; l-- ) {
for( int h=; h<fm.b[l]; h++ )
if( abs(h-fm.b[l+])>= ) {
ans += dp[h][l];
//printf( "(h=%d,l=%d)\n", h, l );
}
if( abs(fm.b[l]-fm.b[l+])< ) break;
}
return ans;
} int main() {
// freopen( "windy.in", "r", stdin );
// freopen( "windy.out", "w", stdout );
int A, B, ans;
init();
scanf( "%d%d", &A, &B );
ans = calc(Form(B+))-calc(Form(A));
printf( "%d\n", ans );
}

  

bzoj 1026的更多相关文章

  1. [BZOJ 1026] [SCOI 2009] Windy数 【数位DP】

    题目链接:BZOJ - 1026 题目分析 这道题是一道数位DP的基础题,对于完全不会数位DP的我来说也是难题.. 对于询问 [a,b] 的区间的答案,我们对询问进行差分,求 [0,b] - [0,a ...

  2. [bzoj 1026]windy数(数位DP)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1026 分析: 简单的数位DP啦 f[i][j]表示数字有i位,最高位的数值为j的windy数总 ...

  3. bzoj 1026 [SCOI2009]windy数 数位dp

    1026: [SCOI2009]windy数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline ...

  4. BZOJ 1026 windy数

    Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? In ...

  5. bzoj 1026 [SCOI2009]windy数(数位DP)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4550  Solved: 2039[Submit][Sta ...

  6. BZOJ 1026: [SCOI2009]windy数( dp )

    dp..dp(x, t) 表示共x位, 第x位为t有多少个windy数. 对答案差分, 我们只需统计1 ~ l-1和1 ~ r的windy数数量. 考虑如何计算[1, n]的答案 : 从最高位到最低位 ...

  7. BZOJ 1026 windy数【数位DP】

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 10142  Solved: 4712[Submit][St ...

  8. bzoj 1026 DP,数位统计

    2013-11-20 08:11 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1026 首先我们用w[i,j]表示最高位是第i位,且是j的 ...

  9. bzoj 1026: [SCOI2009]windy数【数位dp】

    忘记limit不能记WA了一发-- 典型数位dp,变成work(r)-work(l-1),然后dfs的时候记录w当前位置,la上一个数选的什么,lm当前位是否有上限,ok当前位是否可以不考虑差大于等于 ...

随机推荐

  1. 5-python的封装与结构 - set集合

    目录 1 封装与解构 1.1 封装 1.2 解构 1.3 Python3的解构 2 set类型 2.1 set的定义 2.2 set的基本操作 2.2.1 增加元素 2.2.2 删除元素 2.2.3 ...

  2. linux的防火墙管理

    换oricle-linux7系统后,发现iptables的管理方法有不小的改动,记录一下遇到的问题. iptables linux系统已经默认安装了iptables和firewalld两款防火墙管理工 ...

  3. Java 序列化工具类

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.misc.BASE64Decoder; import sun.m ...

  4. WebService初识

    Web service 是一种跨编程语言和跨操作系统平台的远程调用技术,即跨平台远程调用技术.也就是说,不管是J2EE架构,还是.net架构 只要按照规范就可以进行通信,实现数据交互等. 这里说的&q ...

  5. Linux 基础目录和命令

    Linux 标准目录结构   初学Linux,首先需要弄清Linux 标准目录结构 / root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home --- 存 ...

  6. Linux下的各类文件

    .a文件是静态链接库文件.所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分.当多个程序都调用相同函数时,内存中就会存在这个函数的多个拷贝,这样就浪费了宝贵的内存资源.. ...

  7. 20165301 预备作业三:Linux安装及命令入门

    预备作业三:Linux安装及命令入门 VirtualBox虚拟机的安装 在进行安装之前,原本以为有了娄老师的安装教程会是一件很容易的事情.万万没想到,在自己实际动手操作中,还是遇到了许多困难.通过与同 ...

  8. Reflow(回流)和Repaint(重绘) (转)

    原文地址:http://blog.csdn.net/qq_18826911/article/details/68924255 首先我们要明白的是,页面的显示过程分为以下几个阶段: 1.生成DOM树(包 ...

  9. java-list-分组

    Map<String, List<Hb12Domain>> groupBy = hb18DomainList.stream().collect(Collectors.group ...

  10. Eclipse如何定位到某一个类所在硬盘上的位置

    解决方法:安装OpenExplorer_1.5.0.v201108051513.jar插件 将OpenExplorer_1.5.0.v201108051513.jar文件添加到Eclipse所在目录下 ...