HDU 3709 Balanced Number

HDU 3709 Balanced Number

题目传送门

一、题目大意

题目大意:求区间[l,r]里面满足平衡数的数的个数

平衡数:可以通过找一个平衡数位,该数位左边的数位乘以偏移距离的和等于右边的数位乘以偏移距离的和。

举个栗子:4139,平衡数位为3,42+1=9,因此该数是平衡数。

二、解题思路

定义状态dp[pos][k][sum]表示枚举到pos位置,当前平衡数位位置为k,前面数位的数乘以偏移距离的和。

最后判断一下是否等于0就行了。

我们可以枚举平衡数位的位置,同时在枚举时维护和就行了。

另外,这个题是做到的第一个前导0有影响的题
如果数为0,是可以的(既符合题意,又确实存在这个数)
如果数为00,是不可以的(符合题意,是平衡数,但是这个数跟0不是一个吗)
所以这个数有几位,数位最大是len,就会多统计了len1个,在计算的时候要除掉
00,000,0000......

三、实现代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 20;
/*
x,y <= 10^{18},用10进制拆分到数组a,20位足够
本题对于内存空间的限制比较极限,如果无脑使用了32,就会使得f的容量超限
32*32*10010=10250240 byte = 10010 kb = 9.775390625 mb
内存上限是:65535kb=64mb
因为C++本身运行还需要一次的内存,64MB是很极限的,所以在多维数组创建时,一定要注意维度的上界
*/
LL a[N];
/*
pos:走到哪个数位,长度最长是N=20
k:以哪个数位为平衡数位,可以是1到20
sum:前面数位的数乘以偏移距离的和,最大偏移量是20,数位最大是9
可以视为
10*20+10*19+....+10*1=10*(1+2+3+...+20)=10*21*10=2100
*/
LL f[N][N][2110];

LL dfs(int pos, int k, int sum, bool lead, bool limit) {
    if (pos == 0) return sum == 0;
    if (sum < 0) return 0;
    if (!lead && !limit && ~f[pos][k][sum]) return f[pos][k][sum];
    int up = limit ? a[pos] : 9;
    LL ans = 0;
    for (int i = 0; i <= up; i++)
        // sum + (pos - k) * i : 这句话很牛X,pos > k 是加,pos < k是减
        ans += dfs(pos - 1, k, sum + (pos - k) * i, lead && i == 0, limit && i == a[pos]);
    if (!limit && !lead) return f[pos][k][sum] = ans;
    return ans;
}

LL calc(LL x) {
    if (x == -1) return 0; //如果输入的是l=0,则返回0
    int al = 0;
    while (x) a[++al] = x % 10, x /= 10;
    LL ans = 0;
    for (int i = al; i; i--) //枚举每一个数位,模拟此位置k为平衡数位
        ans += dfs(al, i, 0, true, true);
    //0,00,000,0000,....
    return ans - al + 1;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    //平衡数是数的本身性质,与给定的区间无关,可以将memset放在循环外初始化
    memset(f, -1, sizeof f);
    int T;
    cin >> T;
    LL l, r;
    while (T--) {
        cin >> l >> r;
        printf("%lld\n", calc(r) - calc(l - 1));
    }
    return 0;
}
posted @   糖豆爸爸  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2017-09-11 ZIP排除指定目录进行压缩
Live2D
点击右上角即可分享
微信分享提示