BZOJ--1026: [SCOI2009]windy数(数位dp)

题意:windy数定义:任意两位相邻数字之间相差>=2,求[a,b]之间的windy数的个数

思路:很标准的数位dp,也比较简单,记忆化搜索dp[num][fre] 表示 前num位数,前一位是fre的windy数的个数。

感想:因为很久没做数位dp了,wa了两次。。不过还好,这个题是很裸的数位dp了。

代码:
#include<bits/stdc++.h>
using namespace std;
#define mod 100003
long long dp[20][20],poit[20],l;
long long n,m,a,b;
long long dfs(int num,int ok,int fre)
{
    if(num<=0) return 1;
    if(ok&&dp[num][fre]) return dp[num][fre];
    int s=ok?9:poit[num];
    long long all=0;
    for(int i=0;i<=s;i++)
    {
        if(fre-i<2&&i-fre<2) continue;
        if(i==0&&fre==-9) all+=dfs(num-1,ok?1:(i!=poit[num]),-9);
        else  all+=dfs(num-1,ok?1:(i!=poit[num]),i);
    }
    if(ok)
    dp[num][fre]=all;
    return all;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    n--;
    l=0;
    while(n)
    {
        poit[++l]=n%10;
        n/=10;
    }
    a=dfs(l,0,-9);
    l=0;
    memset(dp,0,sizeof(dp));
    while(m)
    {
        poit[++l]=m%10;
        m/=10;
    }
    b=dfs(l,0,-9);
    printf("%lld\n",b-a);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值