题目链接:https://vjudge.net/problem/HDU-3709

Balanced Number

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 6615    Accepted Submission(s): 3174

Problem Description
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].
 
Input
The 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 ≤ 1018).
 
Output
For 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
 
Author
GAO, Yuan
 
Source

题解:

1.对于一个数,我们枚举每个位置作为平衡点,去判断是否存在一个位置使得这个数左右平衡。对于非0的数,如果它是平衡数,那么它的平衡点只有一个。(因为假设aaaa0bbb这个数的平衡点0,如果把平衡点往左移,那么左边变轻,右边变重,原本是平衡的,那改变之后就往右倾斜了。同理平衡点往右移。)所以是+1,正好一一对应。但是对于0,它的任意一个位置都可以作为平衡点,所以需要去重。

2. dp[pos][pivot][num]:处理到pos位置,以pivot为平衡点,且左力矩比右力矩大num的情况下,有多少种情况。

问:

1.为什么dp数组要有“pivot”这一维,直接:dp[pos][num]不行吗?

答:虽然有num记录了当前位的“左力矩 - 右力矩”的大小,但是如果两种情况的pivot不同,那么在pos后面的位置,他们的值的变化是不一样的,即这两种情况不是等价的。只有在相同的位置pos下,他们的平衡点pivot相同,且“左力矩 - 右力矩”的大小且相同,后面位置的数字变化才是等价的。

2.dp[pos][leftnum][rightnum] 这样记录不行吗?

答:其实这样跟dp[pos][num]的情况是一样的,都没有记录平衡点pivot的位置,导致后面位置的数值变化可能不等价。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e6+; int digit[];
LL dp[][][]; LL dfs(int pos, int pivot, int num, bool lim)
{
if(!pos) return (num==);
//剪枝,因为先加左边的,后减左边的,最终结果需要为0,如果过程中都出现负数,那减下去更加负,所以不可能符合条件
if(num<) return ;
if(!lim && dp[pos][pivot][num]!=-) return dp[pos][pivot][num]; LL ret = ;
int maxx = lim?digit[pos]:;
for(int i = ; i<=maxx; i++) //num+(pos-pivot)*i: 高位的加, 低位的减。这条式子很漂亮,刚好能满足力矩的计算
ret += dfs(pos-, pivot, num+(pos-pivot)*i, lim&&(i==maxx)); if(!lim) dp[pos][pivot][num] = ret;
return ret;
} LL solve(LL n)
{
int len = ;
while(n)
{
digit[++len] = n%;
n /= ;
} LL ret = ;
for(int i = ; i<=len; i++)
ret += dfs(len, i, , true); /*
为什么要减去len-1呢?原因是“0”这种情况,0在这里的表示是:000……00(len个0)。对于一个数
我们枚举每个位置作为平衡点,去判断是否存在一个位置使得这个数左右平衡。对于非0的数,如果
它是平衡数,那么它的平衡点只有一个,所以是+1,正好一一对应. 但对于000……00来说,它的每个
位置都可以作为平衡点( 因为左右两边都等于0),所以是+len,但是000……00却只是一个数,所以
需要减去重复计算的部分,即len-1.
*/
return ret-(len-);
} int main()
{
LL T, n, m;
scanf("%lld", &T);
memset(dp,-,sizeof(dp));
while(T--)
{
scanf("%lld%lld",&m,&n);
LL ans = solve(n) - solve(m-);
printf("%lld\n", ans);
}
return ;
}

HDU3709 Balanced Number —— 数位DP的更多相关文章

  1. hdu3709 Balanced Number (数位dp+bfs)

    Balanced Number Problem Description A balanced number is a non-negative integer that can be balanced ...

  2. hdu3709 Balanced Number 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709 题目大意就是求给定区间内的平衡数的个数 要明白一点:对于一个给定的数,假设其位数为n,那么可以有 ...

  3. HDU3709:Balanced Number(数位DP+记忆化DFS)

    Problem Description A balanced number is a non-negative integer that can be balanced if a pivot is p ...

  4. HDU 3709 Balanced Number (数位DP)

    Balanced Number Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) ...

  5. hdu3709 Balanced Number 树形dp

    A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. ...

  6. Balanced Number 数位dp

    题意: 给出求ab之间有多少个平衡数   4139为平衡数   以3为轴   1*1+4*2==9*1 思路很好想但是一直wa  : 注意要减去前导零的情况 0 00 000 0000   不能反复计 ...

  7. [HDU3709]Balanced Number

    [HDU3709]Balanced Number 试题描述 A balanced number is a non-negative integer that can be balanced if a ...

  8. 多校5 HDU5787 K-wolf Number 数位DP

    // 多校5 HDU5787 K-wolf Number 数位DP // dp[pos][a][b][c][d][f] 当前在pos,前四个数分别是a b c d // f 用作标记,当现在枚举的数小 ...

  9. HDU3709 Balanced Number (数位dp)

     Balanced Number Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Descript ...

随机推荐

  1. php生成压缩包

    $filename = "./" . date ( 'YmdH' ) . ".zip"; // 最终生成的文件名(含路径) // 生成文件 $zip = new ...

  2. LeetCode OJ--Evaluate Reverse Polish Notation

    http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/ 栈使用 #include <iostream> #inc ...

  3. AC日记——草地排水 codevs 1993

    1993 草地排水 USACO  时间限制: 2 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 在农夫约翰的农场上,每 ...

  4. codevs——1842 递归第一次

    1842 递归第一次  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解       题目描述 Description 同学们在做题时常遇到这种函数 f( ...

  5. 【String】String.format(format,args...)的使用解析

    String.format(format,args...)的使用解析 使用kotlin 中使用示例 ================================================== ...

  6. linux shell简单实现数据库自动备份

    以centos系统为例,实现数据库自动备份.1.写一个shell: 12 #! /bin/bashmysqldump -cp --user=root --password='123' dbName | ...

  7. iOS开发 当前时间 时间戳 转换

    1.今天在做一个webservice的接口的时候,被要求传一个时间戳过去,然后就是开始在Google上找 2.遇到两个问题,一,当前时间转化为时间戳,二,获取的当前时间和系统的时间相差8个小时 一,转 ...

  8. [转]通俗易懂的php多线程解决方案

    原文: https://www.w3cschool.cn/php/php-thread.html --------------------------------------------------- ...

  9. Effective C++ 条款八 别让异常逃离析构函数

    class DBConn //这个class用来管理DBConnction对象 { public:   //自己设计一个新的DBConn接口 方法3 void close() { db.close() ...

  10. ADO.NET 对数据操作 以及如何通过C# 事务批量导入数据

    ADO.NET 对数据操作 以及如何通过C# 事务批量导入数据   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ...