• BZOJ_1026_[SCOI2009]windy数_数位DP


    BZOJ_1026_[SCOI2009]windy数_数位DP

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

    学一下数位DP。

    f[i][j]表示i位数以j开头的windy数个数。转移有f[i+1][k]+=f[i][j](abs(j-k)>=2)

    答案转成[1~R]-[1~L-1]之后按位枚举,每次枚举到当前位上的数减1。

    注意:

    1.枚举到两位差2以内时停止枚举。

    2.答案要加上位数比他小的所有windy数。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    int f[15][15],a,b;
    int c[15],d[15];
    int sol(int x){
        int num=x,cnt=0,ans=0;
        while(num){
            c[++cnt]=num%10;
            num/=10;    
        }for(int i=1;i<=cnt;i++)d[i]=c[cnt-i+1];
        for(int i=1;i<cnt;i++)    
            for(int j=1;j<=9;j++)ans+=f[i][j];
        for(int i=1;i<d[1];i++)ans+=f[cnt][i];
        for(int i=2;i<=cnt;i++){
            for(int j=0;j<d[i];j++){
                if(d[i-1]-j<2&&j-d[i-1]<2)continue;
                ans+=f[cnt-i+1][j];
            }
            if(d[i-1]-d[i]<2&&d[i]-d[i-1]<2)break;
        }
        return ans;
    }
    int main(){
        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(k-j<2&&j-k<2)continue;
                    f[i][j]+=f[i-1][k];
                }
            }
        }
        scanf("%d%d",&a,&b);
        //sol(18717);
        printf("%d
    ",sol(b+1)-sol(a));
    }
    /*
    18716
    38434
    
    5178*/
    
  • 相关阅读:
    Python中__new__和__init__区别
    raid卡MegaCli工具使用说明
    Python之上下文管理
    上传图片同时生成缩略图
    js上传图片预览
    java截取图片部分尺寸
    JAVA图片处理--缩放,切割,类型转换
    Tomcat设置默认启动项目及Java Web工程设置默认启动页面
    java+easyui实例
    easyui datagrid分页要点总结
  • 原文地址:https://www.cnblogs.com/suika/p/8457078.html
Copyright © 2020-2023  润新知