数位DP真的是套路题,今天拿了HJ一手模板,舒服了。
HDU - 3555
ll n;
int digit[20];
ll dp[20][2];
ll dfs(int len, int sta, bool limit){
if(len == 0) return 1;
if(!limit && dp[len][sta]) return dp[len][sta];
int up = limit ? digit[len] : 9;
ll ret = 0;
for(int i = 0; i <= up; i++){
if(sta && i == 9) continue;
ret += dfs(len - 1, i == 4, limit && i == up);
}
if(!limit) dp[len][sta] = ret;
return ret;
}
void solve(ll num){
int tot = 0;
while(num){
digit[++tot] = num % 10;
num /= 10;
}
printf("%lld\n", n + 1 - dfs(tot, 0, 1));
}
int main()
{
int T; scanf("%d", &T);
while(T--){
memset(dp, 0, sizeof dp);
scanf("%lld", &n);
solve(n);
}
return 0;
}
不写dfs的好像就不是很好写了
LL N;
LL S[100];
LL dp[100][3];
void init(){
dp[0][0] = 1;
for(int i = 1 ; i < 21 ; i++){
dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1];
dp[i][1] = dp[i-1][0];
dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1];
}
}
int main()
{
init();
int T; scanf(" %d",&T);
while(T--){
scanf(" %lld",&N);
int len = 0;
while(N){
S[++len] = N % 10;
N /= 10;
}
S[len+1] = 0;
LL ans = 0LL;
bool flag = false;
for(int i = len ; i >= 1 ; i--){
ans += (dp[i-1][2] * S[i]);
if(flag) ans += dp[i-1][0] * S[i];
if(!flag && S[i] > 4) ans += dp[i-1][1];
if(S[i+1] == 4 && S[i] == 9) flag = true;
}
if(flag) ans++;
printf("%lld\n",ans);
}
return 0;
}
HDU - 3652
dp[i] [j] [k] , i 第i位 , j 是 mod , k是状态
0状态 , 前面没有 13
1状态 没有 13 , 但最后一位是 1
2状态 有13
int N;
int dp[30][13][3];
int a[30];
LL dfs(int len , int mod , int status , bool limit){
if(!len) return (status==2) && (!mod);
if(!limit && dp[len][mod][status]) return dp[len][mod][status];
int res = 0;
int ilen = (limit ? a[len] : 9);
for(int i = 0 ; i <= ilen ; i++){
int nxt_mod = (i + mod*10) % 13;
int nxt_status = status;
if(status == 0){
if(i == 1) nxt_status = 1;
} else if(status == 1){
if(i == 3) nxt_status = 2;
else if(i == 1) nxt_status = 1;
else nxt_status = 0;
}
res += dfs(len - 1 , nxt_mod , nxt_status , limit && i == ilen);
}
if(!limit) dp[len][mod][status] = res;
return res;
}
int main()
{
while(~scanf(" %d",&N)){
int len = 0;
while(N){ a[++len] = N % 10; N /= 10; }
a[len+1] = 0;
int ans = dfs(len , 0 , 0 , 1);
printf("%d\n",ans);
}
}