zoukankan      html  css  js  c++  java
  • bzoj1026 windy数(数位dp)

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

    Input
    包含两个整数,A B。

    Output
    一个整数

    Sample Input

    【输入样例一】
    1 10

    【输入样例二】
    25 50

    Sample Output

    【输出样例一】
    9

    【输出样例二】
    20

    【数据规模和约定】
    100%的数据,满足 1 <= A <= B <= 2000000000 。

    分析:数位dp入门题
    首先我们维护一个f[i][j]表示i位数,最高位是j的windy数的数量
    这里写图片描述
    注意一下这里i的循环,我定义的数组是f[N][N],聪明的宝宝一眼就看出循环应该是从2~N-1,然而zz的我把循环写成了2~N,zzz~~~

    之后就是数位dp的经典操作:把数分成若干部分,分部处理
    例:15624
    分成以下部分:
    0~9999
    10000~10999
    11000~11999
    12000~12999
    13000~13999
    14000~14999
    15000~15199
    15200~15299
    15300~15399
    15400~15499
    15500~15599
    15600~15609
    15610~15619
    15620~15624

    在每个部分中累加windy数的个数
    这里写图片描述
    首先把数x用数组存储
    第一个两重循环中要注意,累加的是长度

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    
    using namespace std;
    
    const int N=12;
    int f[N][N]; //f[i][j]表示i位数,最高位是j的windy数的数量
    int A,B,a[15];
    
    int in()
    {
        int t=0;
        char ch=getchar();
        while (ch>'9'||ch<'0') ch=getchar();
        while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-'0',ch=getchar();
        return t;
    }
    
    int abs(int x)
    {
        if (x>=0) return x;
        else return -x;
    }
    
    void cl()
    {
        int i,j,k;
        for (i=0;i<10;i++) f[1][i]=1;
        for (i=2;i<N;i++)  //i<N
            for (j=0;j<10;j++)
                for (k=0;k<10;k++)
                   if (abs(j-k)>=2)
                      f[i][j]+=f[i-1][k];
        return;
    }
    
    int doit(int x)
    {
        if (x==0) return 0;
        int len=0,ans=0;
        while (x) 
        {
            a[++len]=x%10;
            x/=10;
        }
        int i,j,k;
        for (i=1;i<len;i++)
            for (j=1;j<10;j++) ans+=f[i][j];  //j从1开始,最高位不能是0 
        for (i=1;i<a[len];i++)
            ans+=f[len][i];
        for (i=len-1;i>=1;i--)  //i>=1
        {
            for (j=0;j<a[i];j++)  //j<a[i]
                if (abs(a[i+1]-j)>=2) ans+=f[i][j];
            if (abs(a[i+1]-a[i])<2) break;
        }
        return ans;
    }
    
    int main()
    {
        A=in();
        B=in();
        cl();
        printf("%d",doit(B+1)-doit(A));  //
        return 0;
    }
    
  • 相关阅读:
    团队项目-第一阶段冲刺7
    团队项目-第一阶段冲刺6
    Spring Boot 揭秘与实战(七) 实用技术篇
    Spring Boot 揭秘与实战(七) 实用技术篇
    Spring Boot 揭秘与实战(六) 消息队列篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(四) 配置文件篇
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673632.html
Copyright © 2011-2022 走看看