bzoj 1026: [SCOI2009]windy数 数位dp

1026: [SCOI2009]windy数

Time Limit: 1 Sec  Memory Limit: 162 MB
[Submit][Status][Discuss]

Description

  windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?

Input

  包含两个整数,A B。

Output

  一个整数

Sample Input

【输入样例一】
1 10
【输入样例二】
25 50

Sample Output

【输出样例一】
9
【输出样例二】
20

HINT

 

【数据规模和约定】

100%的数据,满足 1 <= A <= B <= 2000000000 。

数位dp,

dp[i][j][k]表示第i位为j的时候前面有无前导零的方案

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-4
#define bug(x)  cout<<"bug"<<x<<endl;
const int N=2e2+10,M=1e6+10,inf=2147483647;
const ll INF=1e18+10,mod=2147493647;
ll bit[N];
ll f[N][20][2];
ll dp(int pos,ll pre,int flag,int gg)
{
    if(pos==0)return 1;
    if(flag&&f[pos][pre][gg]!=-1)return f[pos][pre][gg];
    ll x=flag?9:bit[pos];
    ll ans=0;
    for(ll i=0;i<=x;i++)
    {
        if(!gg)
        {
            if(i)
                ans+=dp(pos-1,i,flag||i<x,1);
            else
                ans+=dp(pos-1,i,flag||i<x,gg);
        }
        else if(abs(pre-i)>=2)
            ans+=dp(pos-1,i,flag||i<x,gg);
    }
    return f[pos][pre][gg]=ans;
}
ll getans(ll x)
{
    memset(f,-1,sizeof(f));
    int len=0;
    while(x)
    {
        bit[++len]=x%10;
        x/=10;
    }
    return dp(len,0,0,0);
}
int main()
{
    ll l,r;
    scanf("%lld%lld",&l,&r);
    //cout<<getans(r)<<" "<<getans(l-1)<<endl;
    printf("%lld\n",getans(r)-getans(l-1));
    return 0;
}

 

posted @ 2017-03-19 19:13  jhz033  阅读(...)  评论(... 编辑 收藏