题目描述
https://www.luogu.com.cn/problem/P2657https://www.luogu.com.cn/problem/P2657
参考思路
参考代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<sstream>
#include<string>
#include<map>
using namespace std;
typedef long long ll;
#define fo(i,l,r) for (int i = l; i <= r; ++i)
#define F 100005
/*
2547
(4,1)=1000-1999
(3,0)=2001-2099
(3,4)=2400-2499
(2,0)=2501-2509
(2,1)=2510-2519
(2,2)=2520-2529
(2,3)=2530-2539
4被舍弃了
每次位数减少都会继承上面位数所有没取到的数字
*/
int a[11];//存每一个数字
int dp[11][11];//有i位数(i>0)时,最高位为j的windy个数
int fun(int x)//22315
{
if (x == 0)return 0;
int sum = 0;
int ant = 0;
while (x)
{
a[++ant] = x % 10; x /= 10;//2547
}
int now = 0, last = -2;//保证最高位可以有数
for (int i = ant; i >= 1; --i)//从最高位开始
{
now = a[i];//2 5 4 7
for (int j = (i == ant); j < now; ++j)//1 (这样子不包括前导0) 后面就依次遍历0-9
{
if (abs(j - last) >= 2)
sum += dp[i][j];
}
if (abs(now - last) < 2)break;//后面不用做了
last = now;//继承上一位
if (i == 1)sum++;//要有机会来到这里
}
//由于答案是四位的 我们继续求剩下的即可
fo(i, 1, ant - 1)
fo(j, 1, 9)
sum += dp[i][j];
return sum;
}
int main()
{
int l, r;
cin >> l >> r;
//预处理 (1,0)=1 (1,1)=1
fo(i, 0, 9)dp[1][i] = 1;
fo(i, 2, 10)//位数(最高11位)
fo(j, 0, 9)//最高位为j 等一下去掉这个试一下
fo(k, 0, 9)//(2,1)=(1,3)+(1,4)+... (2,3)=(1,0)+(1,1)+(1,5)+...
{
if (abs(j - k) >= 2)
dp[i][j] += dp[i - 1][k];
}
cout << fun(r) - fun(l - 1) << endl;
return 0;
}
检尺 摄行