• Luogu p3413(数位dp)


    传送门

    题意:

    给你一个区间([l,r]),让你求着个区间中,存在长度至少为(2)的回文子串的数的个数。

    分析:

    因为所要求的区间相当的大,因此我们不妨从它的数位入手进行(dp)

    根据萌数的性质,倘若要满足一个长度为(len)的字符串是萌数,那么这个串只需至少包含一个长度为(2)(对应偶回文),或者至少包含一个长度为(3)(对应奇回文)的回文串即可。至此,我们将题目进行了转化,即:如果一个串包含有一个长度为(2)或者长度为(3)的字符串,那么这个数就是萌数。

    因此我们只需要讨论一个串的当前位(pos),它的前一位(pre1),以及它的前两位(pre2)即可。因此我们可以设计一个(dp[pos][pre1][pre2])(dp)数组。但是我们发现,如果这样去设计状态的话,部分合法以及非法状态会发生重叠:如果当前的枚举到的状态是(dp[1][2][3])的状态(即代表枚举到的子串的状态位(123))。此时的这个状态中,合法状态(33123)以及非法状态(45123)将会发生重叠。因此为了防止这种情况,我们考虑再开多一维判断是否在之前是否已经合法子串。故我们可以设计(dp[pos][pre1][pre2][exist])代表,当前位置位(pos),前一位为(pre1),前两位为(pre2),且之前存在/不存在子串的方案数。

    而我们发现,当设计了(exist)这个状态之后,我们就不需要记录前两位(pre2)的信息了,因此我们只需要开一个三维的(dp)数组(dp[pos][pre1][exist])即可。

    而把状态设计好之后,我们就只需要直接套用记忆化搜索的数位dp的板子就可以很简单的结局了。

    代码:

    #include <bits/stdc++.h>
    #define maxn 1005
    using namespace std;
    typedef long long ll;
    ll dp[maxn][15][2];
    char L[maxn],R[maxn];
    int bit[maxn],len;
    const int mod=1e9+7;
    ll dfs(int pos,int pre1,int pre2,int exist,int lead,int limit){
        if(pos==0) return exist;
        if(pre1!=-1&&pre2!=-1&&!lead&&!limit&&dp[pos][pre1][exist]!=-1)
            return dp[pos][pre1][exist];
        int up=limit?bit[pos]:9;
        ll res=0;
        for(int i=0;i<=up;i++){
            int p=(lead&&i==0)?-1:i;
            res+=dfs(pos-1,p,pre1,exist|(p!=-1 && (p==pre1||p==pre2)),p==-1,limit&&(p==up));
            res%=mod;
        }
        if(pre1!=-1&&pre2!=-1&&!lead&&!limit) dp[pos][pre1][exist]=res;
        return res;
    }
    ll solve(char *str,bool sub){
        len=strlen(str);
        for(int i=1;i<=len;i++)
            bit[len-i+1]=str[i-1]-'0';
        if(sub){
            int now=1;
            while(bit[now]==0) bit[now++]=9;
            bit[now]--;
            while(!bit[len] && len) len--;
        }
        memset(dp,-1,sizeof(dp));
        return dfs(len,-1,-1,0,1,1);
    }
    int main()
    {
        scanf("%s%s",L,R);
        printf("%lld",((solve(R,0)-solve(L,1))%mod+mod)%mod);
        return 0;
    }
    
  • 相关阅读:
    Android:CheckBox控件
    Android:RadioGroup,RadioButton
    Android:ImageView控件显示图片
    Spark:reduceByKey函数的用法
    HIve:beeline终端上在输错hive语句时,无论 Backspace还是delete 都删除不掉错误的语句,没有办法退格
    orchard-1.9.2-1.10.2汉化
    Hive:表1inner join表2结果group by优化
    hive:某张表进行分页
    hive:创建索引
    Android:后台给button绑定onClick事件、当返回项目到手机页面时提示是否退出APP
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11287466.html
Copyright © 2020-2023  润新知