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


1026: [SCOI2009] windy数##

  Time Limit: 1 Sec
  Memory Limit: 162 MB

Description###

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

Input###

  包含两个整数,A B。
  

Output###

  一个整数
  

Sample Input 1###

  1 10
  

Sample Output 1###

  9
  

HINT###

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

题目地址:  BZOJ 1026:[SCOI2009]windy数

题解:

     
  裸的数位dp  
  第一次写QAQ,不会01的
www.cnblogs.com/AGFghy/


AC代码

#include<cstdio>
#include<algorithm>
typedef long long ll;
ll a,b;
ll p[20],f[20][15];
ll solve(ll x)
{
    if (x==0) return 0;
    ll y,ans=0,sw,pre;
     
    sw=1;
    while (p[sw]<=x) sw++;
    sw--;
    for (int i=1; i<=sw-1; i++)
        for (int j=1; j<=9; j++)
            ans+=f[i][j];       
     
    y=x/p[sw];
    for (int i=1; i<y; i++)  
        ans+=f[sw][i];
    x=x%p[sw];
    pre=y;
     
    sw--;
    while (sw>0)
    {
        y=x/p[sw];
        for (int i=0; i<y; i++)
            if (abs(pre-i)>=2) ans+=f[sw][i];
        if (sw==1) 
            if (abs(pre-y)>=2) ans+=f[sw][y];
         
        if (abs(y-pre)<2) break;
        x=x%p[sw];
        pre=y;
        sw--;
    }
    return ans;
}
int main()
{
    scanf("%lld%lld",&a,&b);
    p[1]=1;
    for (int i=2; i<=12; i++)
        p[i]=p[i-1]*10;
    for (int i=0; i<=9; i++)
        f[1][i]=1;
    for (int i=2; i<=10; i++)
        for (int j=0; j<=9; j++)
            for (int k=0; k<=9; k++)
                if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
     
    printf("%lld\n",solve(b)-solve(a-1));
    return 0;
}
原文地址:https://www.cnblogs.com/AGFghy/p/9328631.html