HDU 3709 数位DP

来源:互联网 发布:js 数组 slice 编辑:程序博客网 时间:2024/05/16 09:47

点击打开链接

题意:类似天平,若一个数以某一位当支点,两边的数以题目中那样计算的和相等,这这个数使我们要的,问区间共有多少个

思路:操作是一样的,只是我们需要枚举一下支点的位置即可,但是注意因为0是可以的,所以我们最后加的结果要减去1,因为00这样只能当作一个0来计算

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const ll INF=0x3f3f3f3f3f3f3f3fll;const int maxn=5010;int dig[30];ll dp[20][20][1500];ll dfs(int pos,int deep,int lim,int num,int flag){    if(pos<0){        if(flag) return 1;        else if(num==0) return 1;        else return 0;    }    if(!lim&&dp[pos][deep][num]!=-1) return dp[pos][deep][num];    int las=lim?dig[pos]:9;    ll ret=0;    for(int i=0;i<=las;i++){        if(flag==1){            if(i==0) ret+=dfs(pos-1,deep,lim&&(i==las),0,1);            else ret+=dfs(pos-1,deep,lim&&(i==las),i*(pos-deep),0);        }else ret+=dfs(pos-1,deep,lim&&(i==las),i*(pos-deep)+num,0);    }    if(!lim) dp[pos][deep][num]=ret;    return ret;}ll slove(ll n){    if(n==-1) return 0;    int len=0;    ll ret=0;    while(n){        dig[len++]=n%10;        n/=10;    }    for(int i=len-1;i>=0;i--) ret+=dfs(len-1,i,1,0,1)-1;    return ret;}int main(){    memset(dp,-1,sizeof(dp));    int T,cas=1;    ll n,m;    scanf("%d",&T);    while(T--){        scanf("%I64d%I64d",&n,&m);        if(n==0&&m==0) printf("1\n");        else if(n==0) printf("%I64d\n",slove(m)+1);        else printf("%I64d\n",slove(m)-slove(n-1));    }    return 0;}

0 0