• BZOJ1026: [SCOI2009]windy数


    Time Limit: 1 Sec  Memory Limit: 162 MB

    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 。

    Source

    递推方程很好想,用f[i][j]表示i位数第i位为j的数的个数

    对于一个数想求比它小的有多少个windy数,用752举例

    首先求1~699

    接着700~749

    最后750~752另一件事,为什么要记录并递推f[i][0],并且把f[1][0]标记为1

    对于702的递推如果不递推f[2][0]就无法统计。

    对于20如果不把f[1][0]标记为1也无法统计。

    而且由于求的是一段区间,所以答案不会改变。

    #include<cstdio>
    typedef long long ll;
    ll f[11][10];
    int cf[11];
    int jdz(int a)
    {
        return a>0?a:-a;
    }
    ll cnt(ll a)
    {
        int len=1;
        ll re=0;
        for(;a;len++,a/=10) cf[len]=a%10;
        for(int i=2;i<len;i++) re+=f[i-1][0]+f[i-1][1];//对于最高位0的其实并不需要保证第i-1不为1,0.所以这一部分会少统计
        for(int sg=-2,ssg=-10,i=len-1;i;i--)
        {
            for(int j=cf[i]-1;j>=0;j--)
                if(sg-j>1||j-sg>1) re+=f[i][j];
            if(sg<0) sg=cf[i];
            else ssg=sg,sg=cf[i];
            if(jdz(ssg-sg)<2) break;
        }
        return re;
    }
    int main()
    {
        ll l,r;
        scanf("%lld%lld",&l,&r);
        for(int i=0;i<10;i++) f[1][i]=1;
        for(int i=2;i<=10;i++)
            for(int j=0;j<10;j++)
                for(int k=0;k<10;k++)
                    if(j-k>1||k-j>1) f[i][j]+=f[i-1][k];
        printf("%lld
    ",cnt(r+1)-cnt(l));
        return 0;
    }
  • 相关阅读:
    刷面经笔记2019.02.11
    刷面经笔记2019.02.10
    刷面经笔记2019.02.09
    刷面经笔记2019.02.07
    刷面经笔记2019.02.05
    刷面经笔记2019.01.31
    刷面经笔记2019.01.30
    刷面经笔记2019.01.28
    头条2020届实习生笔试题
    金s办公软件web前端笔试题
  • 原文地址:https://www.cnblogs.com/bzmd/p/6264890.html
Copyright © 2020-2023  润新知