[Luogu P2657] [BZOJ 1026] [SCOI2009]windy数

洛谷传送门
BZOJ传送门

题目描述

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为 2 2 2的正整数被称为windy数。 windy想知道,

A A A B B B之间,包括 A A A B B B,总共有多少个windy数?

输入输出格式

输入格式:

包含两个整数, A   B A\ B A B

输出格式:

一个整数

输入输出样例

输入样例#1:
1 10
输出样例#1:
9
输入样例#2:
25 50
输出样例#2:
20

说明

100 % 100\% 100%的数据,满足 1 ≤ A ≤ B ≤ 2000000000 1 \le A \le B \le 2000000000 1AB2000000000

解题分析

显然我们可以预处理出一共有 i i i位, 最高位为 j j j w i n d y windy windy数个数。 按照套路, 我们只需要得到 [ 1 , l e f − 1 ] [1,lef-1] [1,lef1] w i n d y windy windy数个数和 [ 1 , r i g ] [1,rig] [1,rig] w i n d y windy windy数个数即可。现在我们只讨论 [ 1 , k ] [1,k] [1,k] w i n d y windy windy数个数。

k k k m m m位, 最高位为 t t t, 那么我们分以下情况考虑:

  1. 位数 &lt; m &lt;m <m的情况, 直接累加即可。
  2. 位数 = m =m =m, 但最高位 &lt; t &lt;t <t的情况, 仍然直接累加。
  3. 位数 = m =m =m,最高位 = t =t =t的情况, 考虑次高位为 x x x, 直接累加次高位 0 ∼ x − 1 0\sim x-1 0x1的结果, 继续如此计算下去。 注意如果某两位原本的差就 &lt; 2 &lt;2 <2直接 b r e a k break break, 因为我们考虑的是更高位取满的情况。

这样有一个小锅: 因为我们始终累加到当前考虑的最高位的数位 − 1 -1 1(因为最高位可能取不满), 所以实质上我们的 s o l v e ( n ) solve(n) solve(n)算出来的是 n − 1 n-1 n1的结果, 预先 + 1 +1 +1即可。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
#define MX 12
template <class T> IN T abs(T a) {return a > 0 ? a : -a;}
ll dp[MX][10];
int buf[MX];
void init()
{
    for (R int i = 0; i <= 9; ++i) dp[1][i] = 1;
    for (R int i = 2; i <= 10; ++i)
    {
        for (R int j = 0; j <= 9; ++j)
        for (R int k = 0; k <= 9; ++k)
        if(abs(j - k) >= 2) dp[i][j] += dp[i - 1][k];
    }
}
int solve(R int lim)
{
    if(lim == 0) return 0;
    int ans = 0, len = 0;
    W (lim) buf[++len] = lim % 10, lim /= 10;
    for (R int i = len - 1; i; --i)
    for (R int j = 1; j <= 9; ++j) ans += dp[i][j];
    for (R int i = 1; i < buf[len]; ++i) ans += dp[len][i];
    for (R int i = len - 1; i; --i)
    {
        for (R int j = 0; j < buf[i]; ++j)
        if(abs(j - buf[i + 1]) >= 2) ans += dp[i][j];
        if(abs(buf[i + 1] - buf[i]) < 2) break;
    }
    return ans;
}
int main(void)
{
    int lef, rig;
    init();
    scanf("%d%d", &lef, &rig);
    printf("%d", solve(rig + 1) - solve(lef));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值