[HDU4734] [2013成都网络赛] F(x) [数位dp]

[ L i n k \frak{Link} Link]


题目要求求出在 [ 0 , B ] [0,B] [0,B] F ( x ) ≤ F ( A ) F(x)\le F(A) F(x)F(A) x x x个数。
很自然会联想到用数位 d p dp dp来解决。

观察 F ( A ) F(A) F(A)的形式。
题目给出了 F ( A ) = ∑ i = 1 n A i 2 i − 1 F(A)=\sum\limits_{i=1}^nA_i2^{i-1} F(A)=i=1nAi2i1;联想到有 A = ∑ i = 1 n A i 1 0 i − 1 A=\sum\limits_{i=1}^nA_i10^{i-1} A=i=1nAi10i1
那么 F ( A ) F(A) F(A)要怎么嵌入数位 d p dp dp
注意到 n ≤ 9 n\le9 n9 F ( A ) ≤ 4599 F(A)\le4599 F(A)4599,或许可以把 F ( x ) F(x) F(x)存进状态里面
这样的话就是 f ( d i g i t , F x ) f(digit,Fx) f(digit,Fx)表示 d i g i t digit digit位后, F ( x ) ≤ F x F(x)\le Fx F(x)Fx x x x的数量


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<cctype>
using namespace std;
int A,B;
int F[12][4605];
int bit[12];
int calc(int x) {
	int ret = 0, add = 1;
	while (x) {
		ret += x % 10 * (add <<= 1);
		x /= 10;
	}
	return ret;
}
int dfs(const int &pos, const int &state, const bool &limit) {
	if (!pos) {
		return state >= 0;
	}
	if (state < 0) {
		return 0;
	}
	if (!limit && F[pos][state] != -1) {
		return F[pos][state];
	}
	int retVal = 0, up = limit ? bit[pos] : 9;
	for (int i = 0; i <= up; ++i) {
		retVal += dfs( pos - 1, state - i * (1 << pos), limit && i == up );
	}
	if (!limit) {
		F[pos][state] = retVal;
	}
	return retVal;
}
int solve(int x,const int &y) {
	bit[0] = 0;
	while (x) {
		bit[ ++bit[0] ] = x % 10;
		x /= 10;
	}
	return dfs(bit[0], calc(y), true);
}
int main() {
	int T;
	scanf("%d", &T);
	
	memset( F, -1, sizeof(F) );
	for (int caseNumber = 1; caseNumber <= T; ++caseNumber) {
		scanf( "%d%d", &A, &B);
		printf( "Case #%d: %d\n", caseNumber, solve(B, A) );
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值