Java教程

HDU4734 F(x) (数位DP)

本文主要是介绍HDU4734 F(x) (数位DP),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

(如此简短的题目给人一种莫名的压迫感......)

题目中定义一个数的权值求解函数:F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. 观察可知:权值的表达式与数的位数相关,再加上要分离每个位上的数字,那么就不难想到数位DP了。

dp[pos][j]表示pos位下小等于j的元素个数,代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=50000;
 5 int dig[25],a,b;
 6 int dp[11][N];
 7 
 8 int dfs(int pos,int fa,bool limit){
 9     if(pos==0) return fa>=0;
10     if(fa<0) return 0;//剪枝
11     if(!limit&&dp[pos][fa]!=-1) return dp[pos][fa];
12     int len=limit?dig[pos]:9;
13     int ans=0;
14     for(int i=0;i<=len;i++)
15         ans+=dfs(pos-1,fa-i*(1<<(pos-1)),limit&&i==len);
16     if(!limit) dp[pos][fa]=ans;
17     return ans;
18 }
19 
20 int f(int n){//f函数 
21     int ans=0,len=1;
22     while(n){
23         ans+=n%10*len;
24         len*=2;
25         n/=10;
26     }
27     return ans;
28 }
29 
30 int solve(int x){
31     int pos=0;
32     while(x){
33         dig[++pos]=x%10;
34         x/=10;
35     }
36     return dfs(pos,f(a),1);
37 }
38 
39 int main(){
40     int T,cas=1;
41     scanf("%d",&T);
42     memset(dp,-1,sizeof(dp));
43     while(T--){
44         scanf("%d%d",&a,&b);
45         printf("Case #%d: %d\n",cas++,solve(b));
46     }
47     return 0;
48 }

第10行的剪枝含义:当前的fa已经小于0,说明已经不满足题意了,就没有再递归下去的必要了。

这篇关于HDU4734 F(x) (数位DP)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!