HDU-4734 F(x)(数位DP)

题意:对于一个n位的数x(An,An-1,An-2,An-3...A2A1),定义F(x)=An*2^n-1+An-1*2n-2+..+A1*1。给定两个数A,B,求满足k∈[0,B]且F[k]<=F[A]的数的个数。

比较好写的数位DP。首先一组数据中的每个测试用例的A值不同,为了防止每次都要重新清空dp数组,我们把status值设成F[A]-F[k],每次递归保证status的非负性即可。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
int dp[13][5003];
int num[13];
int F(int x)
{
	int f=1,res=0;
	while(x)
	{
		res+=f*(x%10);
		f<<=1;
		x/=10;
	}
	return res;
}
int dfs(int k,int status,bool ismax)
{
	if(k==0)return 1;
	if(!ismax && ~dp[k][status])return dp[k][status];
	int maxer=ismax?num[k]:9,res=0;
	FOR(i,0,maxer)
		if(status>=i*(1<<k-1))
			res+=dfs(k-1,status-i*(1<<k-1),ismax&&i==maxer);
	if(!ismax)dp[k][status]=res;
	return res;
}
int solve(int A,int B)
{
	int p=0;
	while(B)
	{
		num[++p]=B%10;
		B/=10;
	}
	return dfs(p,A,1);
}

int main()
{
	int T;
	scanf("%d",&T);
	memset(dp,-1,sizeof(dp));
	FOR(Ti,1,T)
	{
		int A,B;
		scanf("%d%d",&A,&B);
		printf("Case #%d: %d\n",Ti,solve(F(A),B));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/paulliant/article/details/80446137