hdu 4734

来源:互联网 发布:知乎专栏怎么收藏 编辑:程序博客网 时间:2024/06/05 08:50

简单数位DP,f[i][j]表示i位的数字有多少个数权值小于j,i位的数是实际意义的i位数,就是是以1--9开头,不包括0、

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <cmath>#include <stack>#include <vector>#include <map>#include <string>#define eps 1e-8#define LL long long#define myabs(x) ((x)>0?(x):(-(x)))using namespace std;const int inf=0x3f3f3f3f;const int maxm=5000;int w[]={1,2,4,8,16,32,64,128,256};LL f[15][maxm+10];int B[15];int main(){    int T;    cin>>T;    int i,j,k,p;    for(i=0;i<=maxm;i++) f[0][i]=1;    for(i=1;i<=9;i++)    {        for(j=0;j<=maxm;j++)        {            for(k=1;k<=9&&((1<<(i-1))*k)<=j;k++)            {                for(p=0;p<i;p++)                    f[i][j]+=f[p][j-(1<<(i-1))*k];            }        }    }    int a,b;    int cas=0;    while(T--)    {        scanf("%d%d",&a,&b);        int len=0,mul=1,sum=0,sum2=0;        while(a)        {            sum+=(a%10)*mul;            mul*=2;            a/=10;        }        while(b)        {            B[len++]=b%10;            b/=10;            sum2+=B[len-1]*w[len-1];        }        LL ans=0;        if(sum2<=sum) ans++;        if(len==1&&B[0]==0) { ans=f[0][sum]; }        else        {            for(i=len-1;i>=0;i--)            {                for(j=0;j<B[i]&&(j*w[i]<=sum);j++)                {                    for(k=i;k>=0;k--)                    {                        ans+=f[k][sum-w[i]*j];                    }                  //  printf("%d %d\n",j,ans);                }                sum-=(w[i]*B[i]);            }        }        printf("Case #%d: %I64d\n",++cas,ans);    }    return 0;}