题解:杠杆数

Posted 24Kmagic

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解:杠杆数相关的知识,希望对你有一定的参考价值。

题目

题目描述

如果把一个数的某一位当成支点,且左边的数字到这个点的力矩和等于右边的数字到这个点的力矩和,那么这个数就可以被叫成杠杆数。
比如4139就是杠杆数,把3当成支点,我们有这样的等式:4 * 2 + 1 * 1 = 9 * 1。
给定区间[x,y],求出在[x,y]中有几个杠杆数。

输入格式

两个数,表示x,y。

输出格式

一个输出,表示区间[x,y]中杠杆数的个数。

输入输出样例

输入
7604 24324
输出
897

解析

这道题属于数位DP。
什么是数位DP呢?
数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数。所谓数位dp,字面意思就是在数位上进行dp咯。数位还算是比较好听的名字,数位的含义:一个数有个位、十位、百位、千位......数的每一位就是数位啦!
之所以要引入数位的概念完全就是为了dp。数位dp的实质就是换一种暴力枚举的方式,使得新的枚举方式满足dp的性质,然后记忆化就可以了。
那么我们定义一个dp数组:dp[pos][pl][num1]表示位数为pos,杠杆支点位置在pl,力矩和为num1的数字的个数。
然后在处理结果方面我们可以使用一个前缀和的思想:solve(x)求的是不大于x的满足条件的数的个数,那么区间[l,r]的答案就是solve(r) - solve(l - 1) 了。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int T;
int dp[20][20][2005],num[205],l,r;
int dfs(int pos,int x,bool flag,bool lim,int num1) {
    if(!pos) return num1 == 0;
    if(!lim && dp[pos][x][num1] != -1) return dp[pos][x][num1];
    int maxx = lim ? num[pos] : 9,ans = 0;
    for(int i = 0; i <= maxx; i++) {
	    if(flag) ans += dfs(pos - 1,x,flag && i == 0,lim && i == maxx,i * (pos - x));
	    else ans += dfs(pos - 1,x,flag && i == 0,lim && i == maxx,num1 + i * (pos - x));
    }
    if(!lim) dp[pos][x][num1] = ans;
    return ans;
}
int solve(int x) {
    int ans = 0,cnt = 0;
    while(x) num[++cnt] = x % 10,x /= 10;
    for(int i = 1; i <= cnt; i++) ans += dfs(cnt,i,1,1,0);
    return  ans - cnt + 1;
}
signed main() {
    memset(dp,-1,sizeof(dp));
    scanf("%lld %lld" ,&l,&r);
    if (!l) printf("%lld\\n" ,solve(r));
    else printf("%lld\\n" ,solve(r) - solve(l - 1));
    return 0;
}

以上是关于题解:杠杆数的主要内容,如果未能解决你的问题,请参考以下文章

什么是OTC场外币币交易所开发合约杠杆交易网站搭建???

如何将片段中的 ListView 对象的数据传递给 Activity?

Leetcode题解....ing python

缺少什么功能才能生成令牌;它可以被杠杆化吗?

去杠杆是什么?

bzoj1042题解