Balanced Number(数位DP)

本文介绍了一种算法,用于计算给定范围内平衡数的数量。平衡数定义为一个非负整数,若将其某一位作为支点,左右两边的数字乘以各自到支点的距离后,所得乘积之和相等,则该数为平衡数。文章详细解释了如何通过深度优先搜索(DFS)和动态规划(DP)的方法来解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D - Balanced Number

 HDU - 3709

A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit. When a pivot is placed at some digit of the number, the distance from a digit to the pivot is the offset between it and the pivot. Then the torques of left part and right part can be calculated. It is balanced if they are the same. A balanced number must be balanced with the pivot at some of its digits. For example, 4139 is a balanced number with pivot fixed at 3. The torqueses are 4*2 + 1*1 = 9 and 9*1 = 9, for left part and right part, respectively. It's your job 
to calculate the number of balanced numbers in a given range [x, y].

InputThe input contains multiple test cases. The first line is the total number of cases T (0 < T ≤ 30). For each case, there are two integers separated by a space in a line, x and y. (0 ≤ x ≤ y ≤ 10 18).OutputFor each case, print the number of balanced numbers in the range [x, y] in a line.Sample Input

2
0 9
7604 24324

Sample Output

10
897

题意:找出区间内平衡数的个数,所谓平衡数,就是以这个数字的某一位为支点,左右两边的数字乘力矩之和相等。
题解:比如4139
digit 4 1 3 9
len  4 3 2 1 对于每一位来说比如第四位4 for循环遍历这一位的数字就是0~4 对于第三位1来说就是遍历0~1。for循环遍历每一位作为支点,然后对于dfs中从最高位到最低位搜一遍,对于4139这个数来说,假设支点在2位置,len从4~1,sum=4*2+1*1+3*0+9*(-1)=0 所以4139是一个平衡数,sum=0,返回1。遍历完所有支点位置以及每一位从0到up,得到的和就是ans值。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 ll dp[20][20][2000];
 8 int digit[110];
 9 //dfs中4个参数,len代表当前所在的位数,zhou代表支点位置 
10 //sum代表支点左边的数乘上力矩的加和-右边的数乘上力矩的加和
11 //当sum为0时 代表以zhou这个位置为支点的存在一个数是平衡数。
12 //limit代表的是每一位的上限 
13 ll dfs(int len,int zhou,int sum,bool limit)
14 {
15     if(!len)
16         return sum?0:1;
17     if(!limit&&dp[len][zhou][sum]!=-1)
18         return dp[len][zhou][sum];
19     if(sum<0)
20         return 0;
21     int up=limit?digit[len]:9;
22     ll ans=0;
23     for(int i=0;i<=up;i++)
24     {
25         ans+=dfs(len-1,zhou,sum+i*(len-zhou),limit&&i==up);// sum+i*(len-zhou)表示当前的某一位上的某个数和它到支点距离的乘积 
26     }
27     if(!limit)
28         dp[len][zhou][sum]=ans;
29     return ans;
30 }
31 ll solve(ll x)
32 {
33     if(x<0)
34         return 0;
35     ll len=0;
36     while(x)
37     {
38         digit[++len]=x%10;
39         x/=10;
40     } 
41     ll ans=0;
42     for(int i=len;i>0;i--)
43     {
44         ans+=dfs(len,i,0,true);
45     }
46     return ans-len+1;//因为0 00 000只能算一个 
47 }
48 int main()
49 {
50     int casen;
51     cin>>casen;
52     memset(dp,-1,sizeof(dp));
53     while(casen--)
54     {
55         ll l,r;
56         scanf("%lld%lld",&l,&r);
57         printf("%lld\n",solve(r)-solve(l-1));    
58     } 
59     return 0;
60 } 

 

转载于:https://www.cnblogs.com/1013star/p/10322274.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值