您的位置:首页 > 其它

hdu 4734 F(x)

2013-09-23 20:55 309 查看
         数位dp,数位dp类的题目,一定要想清楚再写代码。如果没想清楚的话最好不要写。。。不然越写越乱。

         dp[ i ][ j ][ k ] 表示为 小于 (j + 1) *  1e i  的所有 x 所组成f (x)等于k 的x的个数。

则有状态转移方程:

         dp[ i ][0 ][ k ] = dp[ i - 1 ][ 9 ][ k ];

         dp[ i ][ j ][ k ] += dp[ i ][ j - 1][ k ];

         dp[ i ][ j ][ k ] += dp[ i ][ 0][ k - (1 << i) * j ];

 然后把状态转化成,dp[ i ][ j ][ k ] 表示小于 (j + 1) *  1e i  的所有 x 所组成f [ x ] 小于等于k 的x的个数。对于A,求出f (A),然后处理B就可以了。对于B分开处理。例如:B = 123;则把B分成 0-99, 100 - 119, 120 - 122, 123 四段来求,就很容易求了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int N = 10;
const int M = (1 << 10) * N;

int dp

[M];
char a
, b
;

void get_dp()
{
int i, j, k, s;
CLR(dp, 0);s = 9;
for(j = 0; j < N; j ++) dp[0][j][j] = 1;
for(i = 0; i < N; i ++)
{
if(i)for(k = 0; k <= s; k ++)
{
dp[i][0][k] = dp[i - 1][9][k];
}
for(j = 1; j < N; j ++)
{
for(k = 0; k <= s; k ++)
{
dp[i][j][k] += dp[i][j - 1][k];
if(i && k >= (1 << i) * j)dp[i][j][k] += dp[i][0][k - (1 << i) * j];
}
}
s = s * 2 + 9;
}
for(i = 0; i < N; i ++)
{
for(j = 0; j < N; j ++)
{
for(k = 1; k < M; k ++)
{
dp[i][j][k] += dp[i][j][k - 1];
}
}
}

}

int main()
{
//freopen("out.txt", "w", stdout);
int t, i, j, tmp, ans, cmp, la, lb, cas = 1;
get_dp();
scanf("%d", &t);
while(t --)
{
scanf("%s%s", a, b);
tmp = 0;i = 0;
la = strlen(a), lb = strlen(b);
for(i = 0; i < la; i ++)
{
tmp += (1 << (la - i - 1)) * (a[i] - '0');
}
i = 0;ans = 0;cmp = 0;
for(i = 0; i < lb; i ++)
{
if(b[i] > '0' && tmp >= cmp)ans += dp[lb - i - 1][b[i] - '0' - 1][tmp - cmp];
cmp += (1 << (lb - i - 1)) * (b[i] - '0');
}
if(cmp <= tmp) ans ++;
printf("Case #%d: %d\n", cas ++, ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数位dp