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\)位不等,枚举第\(i\)位从\(1\)到\(a_{i}-1\),如果第\(i\)位的数\(j\)与\(a_{i+1}\)差的绝对值\(\ge2\),那么这里的答案就是\(f_{i,j}\)。

#include<bits/stdc++.h>
using namespace std;
int f[11][11],a[11];
int abs(int a){return a<0? -a:a;}
void init()
{
    for(int i=0;i<=9;++i) f[1][i]=1;
    for(int i=2,j,k;i<=10;++i) for(j=0;j<=9;++j) for(k=0;k<=9;++k) if(abs(j-k)>=2) f[i][j]+=f[i-1][k];
}
int cal(int x)
{
    int i,j,len=0,ans=0;
    while(x) a[++len]=x%10,x/=10;
    for(i=1;i<len;++i) for(j=1;j<=9;++j) ans+=f[i][j];
    for(i=1;i<a[len];++i) ans+=f[len][i];
    for(i=len-1;i;--i)
    {
    for(j=0;j<a[i];++j) if(abs(j-a[i+1])>=2) ans+=f[i][j];
    if(abs(a[i+1]-a[i])<2) break;
    }
    return ans;
}
int main(){int a,b;init();cin>>a>>b;cout<<cal(b+1)-cal(a);}

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11729087.html

时间: 2024-08-19 00:09:51

Luogu P2657 [SCOI2009]windy数的相关文章

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 >= '

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$,

「 Luogu P2657 」 windy数

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

$P2657\ [SCOI2009]\ windy$数

属于数位\(DP\)入门级别的题目,但我做这类题不多,还是要总结一下这道经典题目 \(Description\) 题面 给定\(a,b\),求\([a,b]\)区间有多少个数满足:任意两个相邻数位之间的差的绝对值\(>=2\) \(a,b<=1e12\) \(Solution\) 数位\(DP\)的基本思想是一个一个数确定,逼近到边界 数位\(DP\)一般设计状态为\(dp[i][s]\)表示当前考虑到第\(i\)位(从最低位编号),当前位置或附近位置状态为\(s\)的方案数. 有时候需要预处

P2657 [SCOI2009]windy数 (数位DP)

题目地址  注意点: 边界讨论. #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int INF=2e9; int dp[15][15]; int maxNum[15];//每一位数字的最大值 int dfs(int len,int lastVal,bool isMaxed,bool isLead){//l

【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

bzoj 1026 [SCOI2009]windy数(数位DP)

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

bzoj1026: [SCOI2009]windy数(数位dp)

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