F(x) HDU - 4734
原题链接
考察:数位dp
思路:
预处理的思路就是像背包dp那样不超过体积V的方案数,这里V对应f(a).
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 13,M = 5000;
int l,r,f[N][N][M],logs[N+2];
void init()
{//共几位 最高位 权值和不超过
logs[0] = 1;
for(int i=1;i<=N;i++) logs[i] = logs[i-1]*2;
for(int i=0;i<=9;i++)
for(int j=i;j<M;j++)
f[1][i][j] = 1;
for(int i=2;i<N;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
for(int s=j*logs[i-1];s<M;s++)
f[i][j][s]+=f[i-1][k][s-j*logs[i-1]];
}
int dp(int n,int li)
{
if(!n) return 1;
vector<int> v;
while(n) v.push_back(n%10),n/=10;
LL res = 0,now = 0;
for(int i=v.size()-1;i>=0;i--)
{
int x = v[i];
for(int j=0;j<x;j++)
if(li-now>=0)
res+=f[i+1][j][li-now];
now+=x*logs[i];
if(now>li) break;
if(!i&&now<=li) res++;
}
return res;
}
int get(int n)
{
int res = 0,k = 1;
while(n)
{
res+=k*(n%10);
k<<=1;
n/=10;
}
return res;
}
int main()
{
int T,kcase = 0;
scanf("%d",&T);
init();
while(T--)
{
scanf("%d%d",&l,&r);
int li = get(l);
printf("Case #%d: %d\n",++kcase,dp(r,li));
}
return 0;
}