hdu3709 Balanced Number 数位dp

来源:互联网 发布:js实现pdf在线阅读 编辑:程序博客网 时间:2024/06/07 06:23

经过这道题对数位dp有了更深的理解。

题意是求一个区间内有多少个平衡数,平衡数是这样定义的,以某一位数为支点,两边的数字乘力矩之和相等。

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.

parse:数位dp无非是把非常多的数表示成不太多的状态数,由最高位向低位递推,每一位会产生一些状态,状态必须可以在位数之间转移,检查最终状态是否符合即可。

这道题有些特殊,除了0之外所有数如果是平衡数都只有一个支点,所以可以枚举支点的位置,这样并不会重复计算,同时记录每一位数字的贡献,最终总贡献为0则符合是平衡数。

#include<iostream>#include<cstring>#include<cstdio>#include<ostream>#include<istream>#include<algorithm>#include<queue>#include<string>#include<cmath>#include<set>#include<map>#include<stack>#include<vector>#define fi first#define se second#define pii pair<int,int>#define inf (1<<30)#define eps 1e-8#define ll long longusing namespace std;const int maxn=110005;const ll mod=1000000007;ll l,r;int d[25];ll dp[25][25][5000];const int N=2000;ll dfs(int pos,int cen,int o,bool flag){    if(pos==-1) {        return o==N;    }    if(flag && dp[pos][cen][o]!=-1)        return dp[pos][cen][o];    ll ans=0;    int mx=flag?9:d[pos];    for(int i=0;i<=mx;i++) {        ans+=dfs(pos-1,cen,o+(cen-pos)*i,flag||i<mx);       // ans%=mod;    }    if(flag)        dp[pos][cen][o]=ans;    return ans;}ll cal(ll u){    if(u==0)        return 1;    int cnt=0;    while(u) {        d[cnt++]=u%10;        u/=10;    }    ll ans=0;    for(int i=cnt-1;i>=0;i--) {        ans+=dfs(cnt-1,i,N,0);    }    ans=ans-(cnt-1);    return ans;}int main(){    int t;    scanf("%d",&t);    memset(dp,-1,sizeof(dp));    while(t--) {        scanf("%I64d%I64d",&l,&r);        ll ans;        if(l>0)            ans=cal(r)-cal(l-1);        else            ans=cal(r);        printf("%I64d\n",ans);    }    return 0;}



0 0
原创粉丝点击