1. 程式人生 > >[HDU4734] [2013成都網路賽] F(x) [數位dp]

[HDU4734] [2013成都網路賽] F(x) [數位dp]

[ L i n k \frak{Link} ]


題目要求求出在 [

0 , B ] [0,B] F ( x
) F ( A ) F(x)\le F(A)
x
x
個數。
很自然會聯想到用數位 d p dp 來解決。

觀察 F ( A ) F(A) 的形式。
題目給出了 F ( A ) = i = 1 n A i 2 i 1 F(A)=\sum\limits_{i=1}^nA_i2^{i-1} ;聯想到有 A = i = 1 n A i 1 0 i 1 A=\sum\limits_{i=1}^nA_i10^{i-1}
那麼 F ( A ) F(A) 要怎麼嵌入數位 d p dp
注意到 n 9 n\le9 F ( A ) 4599 F(A)\le4599 ,或許可以把 F ( x ) F(x) 存進狀態裡面
這樣的話就是 f ( d i g i t , F x ) f(digit,Fx) 表示 d i g i t digit 位後, F ( x ) F x F(x)\le Fx 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;
}