题意:给一个16进制8位数,给定每个数字的贡献,问你贡献和。
思路:数位DP,想了很久用什么表示状态,看题解说用和就行,其他的都算是比较正常的数位DP。
代码:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string>
#include<queue>
#include<set>
#include<vector>
#include<string.h>
#include<algorithm>
typedef long long int ll;
using namespace std;
const int maxn = 1e5 + ;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + ;
ll dp[][];
int bit[];
int num[] = {, , , , , , , , , , , , , , , };
ll dfs(int pos, int sum, bool limit){
if(pos < ) return sum;
if(!limit && dp[pos][sum] != -)
return dp[pos][sum];
int top = limit? bit[pos] : ;
ll ret = ;
for(int i = ; i <= top; i++){
ret += dfs(pos - , sum + num[i], limit && i == top);
}
if(!limit) dp[pos][sum] = ret;
return ret;
} ll solve(ll x){
if(x < ) return ;
ll ans = ;
int pos = ;
memset(bit, , sizeof(bit));
while(x > ){
bit[pos++] = x % ;
x /= ;
}
ans = dfs(, , true);
return ans;
}
char s[];
int main(){
ll fac = ;
for(int i = ; i < ; i++)
fac = fac * + ;
int T;
memset(dp, -, sizeof(dp));
scanf("%d", &T);
while(T--){
ll n, ans = ;
scanf("%lld%s", &n, s);
int pos = ;
ll m = , M;
for(int i = ; i < ; i++){
int c = s[i] >= 'A'? + s[i] - 'A' : s[i] - '';
m = m * + c;
}
M = m + n - ;
if(M > fac){
ans += solve(fac) - solve(m - );
ans += solve(M - fac - );
}
else{
ans += solve(M) - solve(m - );
}
printf("%lld\n", ans);
}
return ;
}