zoukankan      html  css  js  c++  java
  • BZOJ1026 [SCOI2009]windy数

    Description

    一个数被称为 windy 数,当且仅当其满足满足如下条件: 
    • 不含前导零 
    • 相邻两个数字之差至少为 2 
    求在 [ A, B ] 中 windy 数的个数。

    Input

    输入一行两个整数 A, B ( AB2109A≤B≤2∗109 ) 。

    Output

    对于每组测试数据,输出一行一个整数,描述答案。

    Sample Input

    0 2000000000

    Sample Output

    127322182

     
     
    题解:
    做过的第一道数位dp,然而听说暴力可以AC……
    好了,设dp[i][j]表示数位为i最高位为j的windy数数量,转移很好想把,枚举和j绝对值相差大于等于2的数字k,这个就是下一位了,显然把数量移交个他就行了,方程:dp[i+1][k]+=dp[i][j]。然而这题的关键不在方程,而是……
    根本不知道ans存在哪!下面才是正文:
    首先我们可以吧一个数分成3部分:
    记len为有多少的数位;
    1.先统计1~(100000(len个0)-1)中有多少个windy。
    2.统计1000000~(最高位-1)的windy数。
    3.统计剩下的。
    具体看我代码:
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int A,B;
    int dp[12][12],a[12];
     
    void cl(){
        memset(dp,0,sizeof(dp));
    }
     
    void make(){
        for(int i=0;i<=9;i++) dp[1][i]=1;
        for(int i=1;i<=9;i++)
        for(int j=0;j<=9;j++)
        for(int k=0;k<=9;k++)
        if(abs(j-k)>=2) dp[i+1][k]+=dp[i][j];
    }
     
    int get(int x){
        if(x<=0) return 0;
        int len=0,tot=0;
        memset(a,0,sizeof(a));
        while(x) {a[++len]=x%10;x/=10;}
        for(int i=1;i<a[len];i++) tot+=dp[len][i];
        for(int i=1;i<len;i++)
        for(int j=1;j<=9;j++) tot+=dp[i][j];
        for(int i=len-1;i>0;i--){
            for(int j=0;j<a[i];j++){
                if(abs(a[i+1]-j)>=2)
                tot+=dp[i][j];
            }
            if(abs(a[i+1]-a[i])<2) break;
        }
        return tot;
    }
     
    int main(){
        cl();
        make();
        scanf("%d%d",&A,&B);
        printf("%d",get(B)-get(A-1));
    }
  • 相关阅读:
    一些常用的代码评审工具
    Atlassian旗下一干team build软件
    Jira功能全介绍
    项目经验分享
    网址、下载地址
    Java 字节码解读
    Gitlab 安装
    博客园设置
    mybatis 遇到空串无法判断
    Shell 脚本入门
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7192466.html
Copyright © 2011-2022 走看看