很久以前做过的一道数位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. tp修改的写法

  2. 对RSA的认识

     #没有经过专业老师的指导,所以您在阅读本文时建议参考即可. 学习视屏:https://www.youtube.com/watch?v=TqX0AHHwRYQ   https://www.youtub ...

  3. windows环境下搭建Redis集群

    转载请注明出处,原文章地址: https://www.cnblogs.com/tommy-huang/p/6240083.html Redis集群: 如果部署到多台电脑,就跟普通的集群一样:因为Red ...

  4. MongoDB之python简单交互(三)

    python连接mongodb有多种orm,主流的有pymongo和mongoengine. pymongo 安装相关模块 pip install pymongo pymongo操作 主要对象 Mon ...

  5. C# String.Format用法和格式说明

    1.格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元) string.Format("{0:C}",0.2) 结果为:¥0.20 (英文操作系统结果:$0 ...

  6. Vue.js——60分钟快速入门(转)

    var vm = new Vue({ el: '#app', data: { people: [{ name: 'Jack', age: 30, sex: 'Male' }, { name: 'Bil ...

  7. Codeforces 799B - T-shirt buying(STL)

    题目链接:http://codeforces.com/problemset/problem/799/B 题目大意:有n件T恤,每件T体恤都分别有价格(每件衣服的价格不重复).前面的颜色.背部的颜色三种 ...

  8. Codeforces Round #423 Div. 2 C-String Reconstruction(思维)

    题目大意:告诉你n个字符串以及这些字符串在字符串s中出现的位置(x1,x2.....xn),要求在满足上述条件的情况下,求出字典序最小的字符串s. 解题思路:主要问题是,如果直接模拟是会超时的,比如v ...

  9. css 资料链接

    https://tink.gitbooks.io/fe-collections/content/ch03-css/float.html https://css-tricks.com/almanac/p ...

  10. day6 os模块

    OS模块 提供对操作系统进行调用的接口     (1)os.getcwd()   获取当前工作目录,即当前python脚本工作的目录路径 >>> os.getcwd()     获取 ...