• 「题解」:windy数


    问题: windy数

    时间限制: 1 Sec  内存限制: 512 MB

    题面


    题目描述

    Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为

    的正整数被称为 Windy 数。

    Windy 想知道,在A和B之间,包括A和B,总共有多少个 Windy 数?

    输入格式

    一行两个数,分别为 A,B

    输出格式

    输出一个整数,表示答案。

    样例输入

    1 10

    样例输出

    9

    题解


    我的数位dp入门题,嗯,其实挺easy的。

    设f[i][j]表示填了i位数,最高位是j的windy数的个数。

    于是不考虑神特么的先导0问题单考虑一下临位差距至少为2的问题直接大力dp算出所有的值。

    然后再来一遍大力dp,j从1-9循环累加答案就可以了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define int long long
    #define rint register int
    #define ll long long
    using namespace std;
    int f[20][15]={0},a,b;
    ll pw[15];
    void prework()
    {
        pw[0]=1;
        for(rint i=1;i<=12;++i)pw[i]=pw[i-1]*10;
        for(rint i=0;i<=9;++i)f[1][i]=1;
        for(rint i=2;i<=11;++i)//枚举数位
            for(rint j=0;j<=9;++j)//枚举最高位
                for(rint k=0;k<=9;++k)//枚举上一个状态的最高位,本状态的次高位
                    if(abs(j-k)>=2)f[i][j]+=f[i-1][k];
    }
    int count(int x)
    {
        int w=0,y,ans=0,pre;
        while(pw[w]<=x)++w;//求位数
        for(rint i=1;i<w;++i)//枚举位数
            for(rint j=1;j<=9;++j)//枚举最高位
                ans+=f[i][j];
        y=x/pw[w-1];
        for(rint i=1;i<y;++i)ans+=f[w][i];
        pre=y;
        x%=pw[w-1];
        for(rint i=w-1;i>=1;--i)
        {
            y=x/pw[i-1];
            for(rint j=0;j<y;++j)
                if(abs(j-pre)>=2)
                    ans+=f[i][j];
            if(abs(pre-y)<2)break;
            pre=y;
            x%=pw[i-1];
        }
        return ans;
    }
    signed main()
    {
        scanf("%lld %lld",&a,&b);
        prework();
        cout<<count(b+1)-count(a)<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    csu1217: 奇数个的那个数
    小试SAS 判别分析
    bfs poj2965
    STL set常用操作
    csu1002 A+B(III)
    HDOJ 1002 的几种方法
    SQL知识积累
    CSV文件格式介绍
    ASP.net Web Form 知识积累
    C# 位域[flags] 枚举
  • 原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11311352.html
Copyright © 2020-2023  润新知