windy数 (数位DP)

题目描述

https://www.luogu.com.cn/problem/P2657icon-default.png?t=M1H3https://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;
}

检尺 摄行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值