「SCOI2009」windy数

传送门
Luogu

解题思路

数位 \(\text{DP}\)
设状态 \(dp[now][las][0/1][0/1]\) 表示当前 \(\text{DP}\) 到第 \(i\) 位,前一个数是 \(las\),有没有顶到上界,有没有前导零的答案。
转移十分显然。

细节注意事项

  • 咕咕咕

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#include <vector>
#define rg register
using namespace std;

template < typename T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) s = s * 10 + c - 48, c = getchar();
    s = f ? -s : s;
}

const int _ = 11;

int a[_], dp[_][_];

inline int dfs(int now, int las, int lim, int zero) {
    if (now == 0) return 1;
    if (!lim && !zero && dp[now][las] != -1) return dp[now][las];
    int res = 0, tp = lim ? a[now] : 9;
    for (rg int j = 0; j <= tp; ++j)
        if (abs(j - las) >= 2) {
            int _lim = lim && j == tp;
            int _zero = zero && j == 0;
            int _las = _zero ? -2 : j;
            int _now = now - 1;
            res += dfs(_now, _las, _lim, _zero);
        }
    if (!lim && !zero) dp[now][las] = res;
    return res;
}

inline int solve(int x) {
    int n = 0;
    for (rg int i = x; i; i /= 10) a[++n] = i % 10;
    memset(dp, -1, sizeof dp);
    return dfs(n, -2, 1, 1);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
#endif
    int l, r;
    read(l), read(r);
    printf("%d\n", solve(r) - solve(l - 1));
    return 0;
}

完结撒花 \(qwq\)

原文地址:https://www.cnblogs.com/zsbzsb/p/11746554.html

时间: 2024-10-07 18:37:48

「SCOI2009」windy数的相关文章

「CQOI2015」选数

「CQOI2015」选数 题目描述 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个.由于方案数较大,你只需要输出其除以1000000007的余数即可. 输入输出格式 输入格式: 输入一行,包含4个空格分开的正整数,

bzoj1026【SCOI2009】windy数

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

JZOJ 1039. 【SCOI2009】windy数

题目 Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数.windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 两个整数,A B. Output 一个整数,表示A~B中有多少个windy数. Sample Input 1 10 Sample Output 9 Data Constraint Hint 100%的数据,满足 1 <= A <= B <= 2000000000 . 分析 数位D

「 Luogu P2657 」 windy数

# 题目大意 给出区间 $[a,b]$,求出区间中有多少数满足下列两个条件 不含有前导 $0$. 相邻两个数字之差的绝对值至少是 $2$. # 解题思路 数位 $DP$,用记忆化搜索来实现.设 $dp[i][j]$ 表示现在已经枚举到第 $i$ 位,第 $i+1$ 位是 $j$ 时一共有多少满足条件的数. 还是直接看代码里的注释吧. # 放上代码 #include <algorithm> #include <iostream> #include <cstring> #i

【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 <

【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

LG4158 「SCOI2009」粉刷匠 线性DP

问题描述 LG4158 题解 设\(opt[i][j][k]\)代表到\((i,k)\)刷了\(j\)次的方案数. 一开始DP顺序有点问题,调了很长时间. 务必考虑清楚DP顺序问题 \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;char ch=1;int fh; while(ch!='-'&&

dtoi4375「BJOI2019」删数

题意: 对于任意一个数列,如果能在有限次进行下列删数操作后将其删为空数列,则称这个数列可以删空.一次删数操作定义如下: 记当前数列长度为 k,则删掉数列中所有等于 k 的数. 现有一个长度为 n 的数列 a,有 m 次修改操作,第 i 次修改后你要回答:经过 i 次修改后的数列 a,至少还需要修改几个数才可删空? 每次修改操作为单点修改或数列整体加一或数列整体减一. 题解:      如果一个我要删去大小为a的数,那么序列长度会变成a-h[a](h[a]为数值a出线的次数).那么我们意会一下这个

【BZOJ】【1026】【SCOI2009】Windy数

数位DP cxlove基础数位DP第三题 = =预处理是个很有用的东西!然后就是分类讨论! 1 /************************************************************** 2 Problem: 1026 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:0 ms 7 Memory:1272 kb 8 ******************************************