• bzoj1026: [SCOI2009]windy数(数位dp)


    1026: [SCOI2009]windy数

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 7812  Solved: 3522
    [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 。

    思路:http://blog.csdn.net/zz_ylolita/article/details/50754618

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    
    using namespace std;
    
    int dig[12];
    int f[12][10];
    //f[i][j]代表长度为i,最高位为j的windy数个数
    
    void init()
    {
       memset(f,0,sizeof(f));
       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(abs(j-k)>1) f[i][j] += f[i-1][k];
    }
    //(0,dig)范围内的windy数个数
    int solve(int x)
    {
       int len=0;
       while(x)
       {
          dig[len++]=x%10;
          x/=10;
       }
       int ans=0;
       //先处理长度小于len的windy数的个数
       for(int i=1;i<len;i++)
         for(int j=1;j<10;j++)//题目要求不含前导0
            ans+=f[i][j];
       for(int j=1;j<dig[len-1];j++) //长度等于len且最高位和原数不同且小于原数的windy数
         ans+=f[len][j];
       for(int i=len-1;i>=1;i--)//依次循环将最高位变为和原数相同
       {
          for(int j=0;j<dig[i-1];j++)
             if(abs(j-dig[i])>1) ans+=f[i][j];
          if(abs(dig[i]-dig[i-1])<=1) break;
       }
       return ans;
    }
    
    int main()
    {
       int dig,b;init();
       while(scanf("%d%d",&dig,&b)!=EOF)
       {
          int ans=solve(b+1)-solve(dig);
          printf("%d
    ",ans);
       }
       return 0;
    }
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int dp[25][25];
    int dig[25],len;
    int dfs(int pos,int pre,int z,int lim)
    {
        if(pos<=0) return 1;
        if(z&&!lim&&dp[pos][pre]!=-1) return dp[pos][pre];
        int num=lim?dig[pos]:9;
        int ans=0;
        if(z==0)
        {
            for(int i=0;i<=num;i++)
              ans+=dfs(pos-1,i,i,lim&&(i==num));
        }
        else
        {
            for(int i=0;i<=num;i++)
            {
                if((i-pre)*(i-pre)<4) continue;
                ans+=dfs(pos-1,i,1,lim&&(i==num));
            }
        }
        if(z&&!lim) dp[pos][pre]=ans;
        return ans;
    }
    int count(int x)
    {
        len=0;
        while(x)
        {
            dig[++len]=x%10;
            x/=10;
        }
        memset(dp,-1,sizeof(dp));
        return dfs(len,0,0,1);
    }
    int main()
    {
        int l,r;
        while(scanf("%d%d",&l,&r)!=-1)
        {
            printf("%d
    ",count(r)-count(l-1));
        }
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    R.java文件介绍
    Windows CE Notification API的使用方法
    Vue.js组件的重要选项
    Vue.js如何划分组件
    细数那些年我用过的前端开发工具
    前端几个常用简单的开发手册拿走不谢
    Bootstrap相关优质项目学习清单
    前端页面实现报警器提示音效果
    人工智能面试题86问,新手找工作必备!
    人工智能面试题86问,新手找工作必备!
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7190924.html
Copyright © 2020-2023  润新知