Luogu P2657 windy数 题解报告

题目传送门

【题目大意】

定义不含前导零且相邻两个数字之差至少为2的数为$windy$数,求在$[A,B]$这个区间内存在多少$windy$数。

【思路分析】

好的据说这是一道数位DP板子题……$mark$一下,不过说实话这题难道不是记忆化搜索吗???QAQ

我们首先把问题转化成求$[1,B]$之间的$windy$数减去$[1,A-1]$之间的$windy$数,然后单独考虑。

设$f[i][j]$表示到第$i$位,前一位数字为$j$的方案数。然后我们为了保证数字不超出范围,要加一个变量记录是否有限制。有限制就意味着$j=a[i-1]$,那么当前第$i$位所放的数就不能超过$a[i]$,无限制就意味着$j<a[i]$,那么当前第$i$为所放的数就可以为$[0,9]$,当然要保证相邻数字之差不小于2。这里有一点要注意一下,就是当某一位数字为0时,相邻位置可以为0或1,所以我们可以把0看作是-2,这样可以保证没有情况被遗漏。

细节还是看代码叭QwQ

【代码实现】

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define g() getchar()
 8 #define rg register
 9 #define go(i,a,b) for(rg int i=a;i<=b;i++)
10 #define back(i,a,b) for(rg int i=a;i>=b;i--)
11 #define db double
12 #define ll long long
13 #define il inline
14 #define pf printf
15 #define mem(a,b) memset(a,b,sizeof(a))
16 using namespace std;
17 ll fr(){
18     ll w=0,q=1;
19     char ch=g();
20     while(ch<‘0‘||ch>‘9‘){
21         if(ch==‘-‘) q=-1;
22         ch=g();
23     }
24     while(ch>=‘0‘&&ch<=‘9‘) w=(w<<1)+(w<<3)+ch-‘0‘,ch=g();
25     return w*q;
26 }
27 ll A,B;
28 int a[15],f[15][10];
29 il int solve(rg int l,rg int lst,bool lim){
30     if(!l) return 1;//如果已经到了最后一位,那么方案数为1
31     if(lst>0&&lim==0&&f[l][lst]!=-1) return f[l][lst];
32     //记忆化,f数组记录的是没有限制的情况下的方案数
33     rg int up=lim?a[l]:9,ans=0,nxt;//up记录上限
34     go(i,0,up){
35         if(abs(lst-i)<2) continue;
36         nxt=i;
37         if(lst==-2&&nxt==0) nxt=-2;
38         ans+=solve(l-1,nxt,lim&&nxt==a[l]);
39     }
40     if(!lim&&lst>0) f[l][lst]=ans;//记录一下答案
41     return ans;
42 }
43 il int work(ll x){
44     rg int len=0;
45     while(x) a[++len]=x%10,x/=10;
46     return solve(len,-2,1);//因为数字是倒序记录的,所以倒序搜索
47 }
48 int main(){
49     //freopen("","r",stdin);
50     //freopen("","w",stdout);
51     A=fr();B=fr();
52     mem(f,-1);
53     pf("%d\n",work(B)-work(A-1));
54     return 0;
55 }

代码戳这里

原文地址:https://www.cnblogs.com/THWZF/p/11580866.html

时间: 2024-10-01 07:18:34

Luogu P2657 windy数 题解报告的相关文章

【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啊 然而这题只要这样

[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任意取

Luogu P1879 玉米田 题解报告

刷水题找自信系列 题目传送门 [题目大意] 有一个$n*m$的矩阵,每个格子为一块土地,我们可以在土地上种草.每块土地有一个值,如果为$0$,则这块土地很贫瘠,不能种草:如果为$1$,则这块土地很肥沃,可以种草.现在要在这个矩阵上种草,要求不能有两个相邻的格子都种了草,求方案数. [思路分析] 因为$n,m\ge12$,所以我们考虑状压.设$f[i][j]$表示第$i$行状态为$j$时的方案数,对于状态$j$要判断是否合法,即判断是否符合土地的贫瘠和肥沃的性质,以及同一行内是否有相邻的格子种了草

Luogu P4204 神奇口袋 题解报告

题目传送门 [题目大意] 一个口袋里装了t种颜色的球,第i种颜色的球的数目为ai,每次随机抽一个小球,然后再放d个这种颜色的小球进口袋. 给出n个要求,第x个抽出的球颜色为y,求满足条件的概率. [思路分析] 抽出一个球颜色为i的概率设为f[i],球的总数为sum 在第k步时,$f[i]=\frac{a[i]}{sum}$ 那么在k+1步就有两种情况: 1.第k步抽中了颜色为i的球,那么此时概率为$\frac{a[i]}{sum}*\frac{a[i]+d}{sum+d}$ 2.第k步没有抽中,

Luogu P1613 跑路 题解报告

题目传送门 [题目大意] [思路分析] 我们设$g[i][j][k]$表示从$i$走$2^k$步能否到达$j$,$d[i][j]$表示$i$到$j$最少要走多少秒. 用倍增预处理出$g$,然后就可以$Floyd$跑最短路啦!QwQ [代码实现] 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6

luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索

题目链接 luogu P2657 [SCOI2009]windy数 题解 我有了一种所有数位dp都能用记忆话搜索水的错觉 代码 #include<cstdio> #include<algorithm> inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c <= '9' && c >= '

Luogu P2657 [SCOI2009]windy数

题目 首先我们可以非常轻松地预处理出\(f_{i,j}\)表示一个最高位为\(i\)位且该位为\(j\)的windy数的个数. 然后我们可以利用经典容斥把答案变成求\([1,x]\)的windy数个数. 设\(x\)有\(len\)位,从低到高位分别是\(a_1,\cdots,a_{len}\) 首先我们把位数小于\(len\)的答案求出. 然后求出位数等于\(len\)且首位小于\(a_{len}\)的答案. 然后我们从大到小枚举\(len\sim i-1\)位相等,\(i\)位不等,枚举第\

P2657 [SCOI2009]windy数

题目描述 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? 输入输出格式 输入格式: 包含两个整数,A B. 输出格式: 一个整数 输入输出样例 输入样例#1: 1 10 输出样例#1: 9 输入样例#2: 25 50 输出样例#2: 20 说明 100%的数据,满足 1 <= A <= B <= 2000000000 . Solution: 本题显然数位$DP$,

windy数(简单数位DP)

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