• [SCOI2009]windy数


    这是本蒟蒻做的第一道数位DP。。。(大佬勿喷QVQ

    这个题据说比较裸?WTF我咋不知道 QVQ

    emm。。。根据题意我们可以发现,通过枚举每个的位置的数我们可以递推出满足条件的数的数量

    这里用 f[i][j] 表示 有 i 位 最高位的数是 j 有f[i][j]个方案

    那么我们就可以 轻松 得到DP柿子啦~~~

    注意:当我们得到A B这两个数的时候,我们要对 B 和 A-1 操作。。。

      为什么A要-1呢?

      因为我们得到的windy数是从 0~B 的那么我们重复的就是 0~A-1 的windy数

    接下来要处理第二步?就是判断哪些答案合法

    合法答案分为三部分:

    假使我们的这个数为 X 有 K 位 一个数组 S 记录每位数是什么

    first:位数小于 K 必然的这些数都小于X 所以我们把 f 数组无脑加上就好

    second:位数等于 K 那么我们首先可以确定,最高位小于 S[K] 的答案肯定合法

    third:下面就是最难搞的地方,我们要一位一位的判断答案的合法性

      举个例子 19260817 135 我们倒着枚举每一位 for(int i=K-1;i>=1;i++);

      我们可以发现对于第 i 位的数,我们可以通过枚举这个数 j,此时要满足两个条件。

      小于 S[i] 而且 abs ( j - S[i] ) >= 2 那么选择这个数一定是合法的。

      依次类推。。。但是,如果当 S[i+1] - S[i] < 2 时 那么以后的数一定是不合法的。。。

      因为这两个数已经不满足条件了。。。

    那么,我们的问题就解决了?

      NO NO NO

    当我们发现每一位都合法,就是这个数本身就是一个windy数那么我们的答案就应该+1

    呆码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #define ll long long
    using namespace std;
    
    ll A,B,f[15][15]; // 多少位数 最高位是多少 有多少方案 
    int s[21];
    
    inline void DP()
    {
        for(int i=0;i<=9;i++)
            f[1][i]=1;
        for(int i=2;i<=10;i++)
            for(int j=0;j<=9;j++)
                for(int k=0;k<=9;k++)
                    if(abs(j-k)>=2)
                        f[i][j]+=f[i-1][k];
    }
    
    inline ll solve(int x)
    {
        memset(s,0,sizeof(s));
        if(x==0) return 0;
        int num=0; ll ans=0;
        while(x)
        {
            s[++num]=x%10;
            x/=10;
        }
        for(int i=1;i<=num-1;i++)
            for(int j=1;j<=9;j++)
                ans+=f[i][j];
        for(int i=1;i<=s[num]-1;i++)
            ans+=f[num][i];
        
        for(int i=num-1;i>=1;i--)
        {
            for(int j=0;j<=s[i]-1;j++)
                if(abs(j-s[i+1])>=2)
                    ans+=f[i][j];
            if(abs(s[i+1]-s[i])<2) break;
            if(i==1) ans+=1;
        }
        return ans;
    }
    
    int main()
    {
        cin>>A>>B;
        DP();
        cout<<solve(B)-solve(A-1);
    }
    蒟蒻的代码,大佬别点开
  • 相关阅读:
    数组中的每一个对象执行一次方法:makeObjectsPerformSelector
    $.each() each
    JQ js选择节点操作
    Sublime Text 3 快捷键
    TotoiseSVN的基本使用方法
    Hbuilder快捷键
    获取网页内容区域各种高/宽汇总
    TP操作
    xhr接收php://output的二进制文件,并转换成excel表格
    Go语言的%d,%p,%v等占位符的使用
  • 原文地址:https://www.cnblogs.com/zzzyc/p/8780173.html
Copyright © 2020-2023  润新知