• 1026: [SCOI2009]windy数


    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 9670  Solved: 4445
    [Submit][Status][Discuss]

    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

    HINT

     

    【数据规模和约定】

    100%的数据,满足 1 <= A <= B <= 2000000000 。

    windy数的大致意思是:像135,6913,13579,这样每两个相邻数字的差≥2

    数位dp:

    正面直接猜想,保存2000000000状态无疑是不可能的,必须采用更加巧妙的方法。

    可以设dp数组为:f[i][j],i表示数字位数,j表示最高位的数字

    因此可以得到dp方程:

    [f[i][j]=sum_{k=0}^{kleq 9} f[i-1][k]left (left | k-j ight |geq 2 ight )]

    但这只计算出最高位为j的结果,无法求出范围内的结果,这时可以转换思想,求出1~b的结果减去1~a-1的结果,不就是答案了吗?

    设len表示数字位数,T[i]表示第i位的数字

    首先,ans加上1~len-1位的情况

    然后ans加上最高位数字为1~T[len]-1的情况

    接着以此类推,加上次最高位1~T[len-1]-1的情况,加上次次最高位1~T[len-2]-1的情况。。。。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cmath>
     5 using namespace std;
     6 
     7 #define LL long long
     8 
     9 int a,b;
    10 LL f[20][10];
    11 
    12 LL solve(int t)
    13 {
    14     LL ans=0;
    15     int len=0,T[20];
    16     while(t)
    17     {
    18         T[++len]=t%10;
    19         t/=10;
    20     }
    21     for(int i=1;i<len;i++)
    22         for(int j=1;j<=9;j++)
    23             ans+=f[i][j];
    24     for(int i=1;i<T[len];i++)
    25         ans+=f[len][i];
    26     for(int i=len-1;i>=1;i--)
    27     {
    28         for(int j=0;j<T[i];j++)
    29             if(abs(j-T[i+1])>=2)
    30                 ans+=f[i][j];
    31         if(abs(T[i]-T[i+1])<2) break;
    32     }
    33     return ans;
    34 }
    35 
    36 int main()
    37 {
    38     scanf("%d %d",&a,&b);
    39     for(int i=0;i<=9;i++) f[1][i]=1;
    40     for(int i=2;i<=15;i++)
    41         for(int j=0;j<=9;j++)
    42             for(int k=0;k<=9;k++)
    43                 if(abs(k-j)>=2)
    44                     f[i][j]+=f[i-1][k];
    45     cout<<solve(b+1)-solve(a)<<endl;
    46     return 0;
    47 }
  • 相关阅读:
    基于注解的IOC配置
    字符串典型问题分析
    指针与数组
    数组的本质
    数组与指针分析
    指针的本质
    #与##操作符使用
    #pragma使用分析
    #error和#line使用分析
    条件编译使用
  • 原文地址:https://www.cnblogs.com/InWILL/p/9255960.html
Copyright © 2020-2023  润新知