牛客IOI周赛25-普及组 B. 学姐的编码1.0(简单DP)
链接:https://ac.nowcoder.com/acm/contest/11232/B
来源:牛客网
题目描述
学姐最近喜欢上了编码,尤其是十六进制编码,但是学姐特别挑剔,在学姐眼中,只有逐位递增的编码才是一个优美的编码,比如12,58都是优美的编码,85,22则都不是优美的编码,现在学姐得到了一个编码串,她希望你告诉她该编码串里可查询到的所有不重复的优美的编码总个数,对于单个字符组成的编码,学姐总是认为这个编码是优美的,且优美的编码当中是允许存在前导零的
编码可查询的判定依据:在给定编码串ss中删去任意k位字符(0≤k<∣s∣),剩下字符不改变顺序组成一个新的编码s1,则认为s1可在s中查询到,如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
实际上就是求不重复的上升子序列的个数。由于序列每个元素的范围很小,因此可以设dp[i]为i结尾的不同的上升子序列的个数。每遍历到一个数x就用比他更小的数的dp值更新他的dp值(满足无后效性)。最后统计答案即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
string s;
map<char, int> mp;
long long dp[30];//dp[j]表示以j结尾的不同的递增子序列的个数
int n;
int get(char x) {
if(x <= \'9\') return x - \'0\';
else return x - \'A\' + 10;
}
signed main() {
cin >> s;
n = s.size();
s = " " + s;
for(int i = 1; i <= n; i++) {
char now = s[i];
int num = get(now);
dp[num] = 1;
for(int j = 0; j < num; j++) {
dp[num] += dp[j];
}
}
long long ans = 0;
for(int i = 0; i <= 15; i++) {
ans += dp[i];
}
cout << ans;
return 0;
}