bzoj1026

http://www.lydsy.com/JudgeOnline/problem.php?id=1026

数位dp。。。

首先我们先把没有限制的dp出来,然后分类讨论,如果最高位比这个数的最高位小或者比这个数短的方案先加上去,然后讨论最高位等于这个数的情况。

比如说54321,我们把<50000的东西全部弄好了。

然后枚举,从a[0]-1开始,我们把(50000,53999)的加上,然后把(54200,54299)的加上,然后把(54300,54319)的加上,注意我们传的参数,最后把(54320,54321)的加上。

因为dp[i]表示第i位,所以每次我们加上的是从第i位到第一位的方案,只要i位和上一位满足条件,就可以加。

总结:先统计宽松的,最后统计天际线附近的,不断逼近。。。

#include<bits/stdc++.h>
using namespace std;
int A, B;
int a[20], dp[20][20];
int solve(int n)
{
    int ret = 0; a[0] = 0;
    while(n) a[++a[0]] = n % 10, n /= 10;
    for(int i = 1; i < a[0]; ++i)
        for(int j = 1; j <= 9; ++j) ret += dp[i][j];
    for(int i = 1; i < a[a[0]]; ++i) ret += dp[a[0]][i];
    for(int i = a[0] - 1; i; --i)
    {
        for(int j = 0; j < a[i]; ++j) if(abs(j - a[i + 1]) >= 2) ret += dp[i][j];
        if(abs(a[i] - a[i + 1]) < 2) break;
    }
    return ret;
}
int main()
{
    for(int i = 0; i <= 9; ++i) dp[1][i] = 1;
    for(int i = 2; i <= 10; ++i)
        for(int j = 0; j <= 9; ++j)
            for(int k = 0; k <= 9; ++k) if(abs(j - k) >= 2) dp[i][j] += dp[i - 1][k];
    scanf("%d%d", &A, &B);
    printf("%d\n", solve(B + 1) - solve(A));
    return 0;
}

时间: 2024-08-03 14:50:15

bzoj1026的相关文章

【bzoj1026】 SCOI2009—windy数

http://www.lydsy.com/JudgeOnline/problem.php?id=1026 (题目链接) 题意 在区间${[A,B]}$有多少个数相邻两个数位上的数之差至少为2. Solution 数位dp,右转题解:LCF 其中${f[i][0]}$,表示的是第${i}$位为${0}$的方案数,并不是不取${i}$位. 细节 LL 代码 // bzoj1026 #include<algorithm> #include<iostream> #include<cs

【BZOJ1026】【SCOI2009】windy数

传送门~:http://www.lydsy.com/JudgeOnline/problem.php?id=1026 数位dp傻题QaQ 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 using namespace std; 6 int f[15][15], A, B, da[15]; 7 void get_ready(){ 8 for

[BZOJ1026][SCOI2009]windy数 解题报告|数位dp

Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 一直还是有点怕数位DP的...包括今天做这道简单的小题也花了很久的时间处理细节. 首先大体的思路非常明显,定义一个DP f[i,j]表示第i位放数字j有多少种方法,可以通过前一位的一些满足的数字推出这一位. 但是如何来解决在某个数A的范围内呢...? 并且一旦前面的没有取满,这一位都是可以0..9任意取

【luogu2657】【bzoj1026】 [SCOI2009]windy数 [动态规划 数位dp]

P2657 [SCOI2009]windy数 bzoj1026 一本通说这是一道数位dp模板题 emmmmm 就是逐位确定 f[i][j]表示填了i位数其最高位数字为j 然后就去求可能方案数 分为 不满足x的位数的严格小于x的全部情况 和x的位数相同 但最高位小于x的最高为的全部方案数 和x的位数相同 有一位比x的对应位数小的全部方案数 其余位数对应数字都相同(这是数位dp常用的一个性质:对于一个小于n的数 它从高位到低位一定会出现某一位上的数字小于n所对应这一位上的数字) PS 因为x不一定为

bzoj1026 [SCOI2009]windy数

1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6392  Solved: 2854[Submit][Status][Discuss] Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 Sample I

bzoj1026: [SCOI2009]windy数 数位dp

题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1026 题意: Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 思路: 数位dp,记忆化搜索. 1 #include <bits/stdc++.h> 2 3 using namesp

【BZOJ1026】【SCOI2009】windy数 数位DP

链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46446473"); } 题解: f(i,j) 表示最高 i 位,此位为 j ,的方案数. 注意此数组存在前导零,比如 f(i,0) . f(i,j) 从 f(i?1,k) 随便转移. 代码: #include <

数位dp——BZOJ1026 Windy数

1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MB Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 Sample Input [输入样例一] 1 10 [输入样例二] 25 50 Sample Output [输出样例

【BZOJ1026】windy数题解

题面 [题目描述] windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? [输入] 包含两个整数,A B. [输出] 一个整数. [输入样例一] 1 10 [输入样例二] 25 50 [输出样例一] 9 [输出样例二] 20 [数据规模和约定] 100%的数据,满足 1 <= A <= B <= 2000000000 . 题解 分析 头一次接触数位DP啊 然而这题只要这样

数位DP初步 bzoj1026 hdu2089 hdu3555

为了搞SCOI的几道题先做水数位.之前听过课,半懂不懂吧,现在清楚了些. 这类题一般满足区间减法,即只需要我们求出(1,n)即可,然后打表也是为了sovle(DataType)服务.先想好怎么计算,再去想怎么打表.计算是一般存在这样的问题,就是比如n=abcdef,当a=6时,6开头的不能全算,那就只能先算1~5,然后理解为把6摆好,算下一位,这样我们发现,这个函数是没有包含n这个数的,所以调用是要调用sovle(n+1) 不要62 Problem Description 杭州人称那些傻乎乎粘嗒