牛客-学姐的编码1.0-dp水题

链接:https://ac.nowcoder.com/acm/contest/11232/B
来源:牛客网

题目描述
学姐最近喜欢上了编码,尤其是十六进制编码,但是学姐特别挑剔,在学姐眼中,只有逐位递增的编码才是一个优美的编码,比如12,58都是优美的编码,85,22则都不是优美的编码,现在学姐得到了一个编码串,她希望你告诉她该编码串里可查询到的所有不重复的优美的编码总个数,对于单个字符组成的编码,学姐总是认为这个编码是优美的,且优美的编码当中是允许存在前导零的

编码可查询的判定依据:在给定编码串ss中删去任意kk位字符(0≤k<|s|)(0≤k<∣s∣),剩下字符不改变顺序组成一个新的编码s1,则认为s1可在ss中查询到,如0102中可查询的编码有0,1,2,00,01,02,10,12,010,012,002,102,0102

输入描述:
一个字符串s表示所给十六进制编码串(1≤|s|≤1000000)
(保证所给编码串与标准十六进制一致,编码串中仅可能出现0-9与A-F,不会有多余字符出现)

输出描述:
一个数,表示不重复计算的情况下优美的编码的总个数

示例1
输入
001A
输出
7

说明:
七种方案分别为
0,01,0A,01A,1,1A,A
备注:
对于10%的数据:1≤n≤5
对于30%的数据:1≤n≤10
对于100%的数据:1≤n≤1000000,其中另有10%保证字符串中0-9与A-F至少各出现一次

简单的dp问题
首先我们可以先将字符’0’ - ‘9’对应数字 0-9
然后将字符’A’ - 'F’对应数字10 - 15

我们用数组dp[i] 表示以i (上面的字符对应的数字) 为结尾的方案数
因为要满足一个单调递增的条件,那么这就是一个前缀的关系,在操作的时候要注意到不能够重复计算贡献
dp[i] == dp[0] + .... + dp[i-1] + 1
一定要注意不能够重复计算,在状态转移的时候,一定要注意将之前的状态进行清空
很容易想到,最终的答案就是dp[0] + dp[1] + .... + dp[15]

int n,m;
string s;
int cnt[maxn];
int main()
{
    cin >> s;
    s = "#" + s;
    int len = s.size()-1;
    for(itn i=1;i<=len;i++)
    {
        int pos = 0;
        if(s[i] >= '0' && s[i] <= '9') pos = s[i] - '0';
        else pos = s[i] - 55;
        cnt[pos] = 1;
        for(int j=0;j<pos;j++) cnt[pos] += cnt[j];
    }
    ll ans = 0;
    for(int i=0;i<maxn;i++){
        ans += cnt[i];
    }
    cout << ans <<endl;
    return 0;
}
posted @ 2021-05-03 20:42  PushyTao  阅读(48)  评论(0编辑  收藏  举报