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;
}
posted @ 2021-05-29 22:53  acmloser  阅读(49)  评论(0编辑  收藏  举报