很久以前做过的一道数位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. Python基础之杂货铺

    字符串格式化 Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-310 ...

  2. BZOJ - Problem 3622 - 已经没有什么好害怕的了

    题意: 给定两个序列$a$和$b$,让它们进行匹配,求出使得$a_i > b_j$的个数比$a_i < b_j$的个数恰好多$k$,求这样的匹配方法数 题解: 这题的各种表示有一点相似又截 ...

  3. openjudge-NOI 2.6-2988 计算字符串距离

    题目链接:http://noi.openjudge.cn/ch0206/2988/ 题解: 首先,题目有误,少了一个添加操作 和求解LCS之类的思路类似 f[i][j]表示a序列中1..i的部分和b序 ...

  4. centos7安装Python3的过程中会和Python2.7版本冲突导致yum版本比对应,致使yum不能使用的问题。

    centos7安装Python3的过程中会和Python2.7版本冲突导致yum版本比对应,致使yum不能使用的问题. 原因:yum调用Python,启动程/usr/bin/yum就是一个python ...

  5. charles抓包误点deny处理办法及日常抓包

    误点deny方法在最底下~~ (博文为转载) 我们在开发网站项目的时候,我们可以通过浏览器的debug模式来看request以及response的数据,那么如果我们开发移动端项目没有网页呢?如何抓取数 ...

  6. TreeSet基本用法

    TreeSet的基础方法: public class TreeSetTest { public static void main(String[] args) { TreeSet nums = new ...

  7. python selenium自动化测试之路(1)--分层测试概念、selenium工具介绍

    1.分层自动化测试概念 传统的自动化市场更关注产品UI层的自动化测试,而分层的自动化测试倡导产品开发的不同阶段都需要自动化测试 大多公司与研发团队其实是忽略了单元测试与集成测试阶段的自动化测试工作,所 ...

  8. python中的any和all函数

    any和all函数是判断一组数据真假性的综合结果.以下摘选自Stackoverflow. ------------------ 分割线开始 ----------------- any any will ...

  9. Python使用opencv

    Python配置opencv 原理 Python调用opencv的原理是:opencv编译出共享库文件,python把这个共享库文件作为一个模块加载并使用. 通俗点就是,编译opencv的时候开启py ...

  10. bzoj 2115 线性基

    这种路径异或问题,可以转换为一条路径和若干个环的线性组合,然后就能用线性基搞了. 复习了一波线性基. #include<bits/stdc++.h> #define LL long lon ...