数位DP入门
数位DP入门(蒟蒻)
概念
所谓数位DP就是指的数位DP,就是对数字的每一位进行DP 。
我们在具体例题中来分析数位DP
P2657 SCOI2009windy数
题目描述
不含前导零且相邻两个数字之差至少为 2 的正整数被称为 windy 数。windy 想知道,在 a 和 b之间,包括 a 和 b ,总共有多少个 windy 数?
输入格式
输入只有一行两个整数,分别表示 a 和 b
输出格式
输出一行一个整数表示答案。
输入1
1 10
输出1
9
输入2
25 50
输出2
20
分析
我们将n的每一位拆分开分别计算它的贡献,从最高位依次固定,设
f[i][j] 表示一共i位,最高位是j的windy数的个数
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 11;
int f[N][10];//f[i][j] 表示一共i位,最高位是j的windy数个数
void init()
{
for(int i=0;i<=9;i++) f[1][i] = 1;//个位数可以取10个
for(int i=2;i<N;i++)
{
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++)
if(abs(j - k) >= 2)
f[i][j] += f[i-1][k];
}
}
int l,r;
int dp(int n)
{
if(n == 0) return 0;
vector<int> v;
while(n) v.push_back(n % 10),n /= 10;//提取每一位
int res = 0;
int last = -2;
for(int i=v.size()-1;i>=0;i--)
{
int x = v[i];
for(int j = i == v.size() - 1;j < x; j++)
{
if(abs(j - last) >= 2)
res += f[i+1][j];
}
if(abs(x - last) >= 2) last = x;
else break;
if(i == 0) res++;
}
for(int i=1;i<v.size();i++)
for(int j=1;j<=9;j++)
res += f[i][j];
return res;
}
int main()
{
init();
cin>>l>>r;
cout<<dp(r) - dp(l - 1);
return 0;
}

浙公网安备 33010602011771号