UOJ Logo zgjkt的博客

博客

【bzoj1026】windy数

2015-04-19 21:48:31 By zgjkt

题目大意

不含前导零且相邻两个数字之差至少为$2$的正整数被称为$windy$数

询问在$A$和$B$之间,包括$A$和$B$,总共有多少个$windy$数

数据范围

$1\leqslant A\leqslant B\leqslant 2\times 10^9$


题解

$opt[i][j]$表示当有一个数有$i$位数,最高位为$j$的$windy$数的个数

$opt[i][j]+=opt[i-1][k](0\leqslant k\leqslant 9\ and\ |j-k|\geqslant 2)$


程序

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define ll long long
#define inf 0x3f3f3f3f

using namespace std;

ll opt[15][15];
int digit[15],len;
ll l,r,sum;

inline void init(){
    scanf("%lld%lld",&l,&r);
    For(i,0,9) opt[1][i]=1;
    For(i,2,10)
        For(j,0,9)
            For(k,0,9)
                if (abs(j-k)>=2) opt[i][j]+=opt[i-1][k];
}

inline ll get(ll x){
    if (!x) return 0;
    len=0,sum=0;memset(digit,0,sizeof(digit));
    while(x) {digit[++len]=x%10;x/=10;}
    For(i,1,len-1)
        For(j,1,9) sum+=opt[i][j];
    For(i,1,digit[len]-1) sum+=opt[len][i];
    for(int i=len-1;i>=1;i--){
        For(j,0,digit[i]-1)
            if (abs(digit[i+1]-j)>=2) sum+=opt[i][j];
        if (abs(digit[i+1]-digit[i])<2) break;
    }
    return sum;
}

int main(){
    init();
    printf("%lld\n",get(r+1)-get(l));
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。