题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4734
题目大意:
给一个数A (十进制表示形式为AnAn-1An-2 ... A2A1,定义函数 F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1,给一个B,求B以内的i,满足F(i)<=F(A)
解题思路:
很裸的数位dp,先求出F(A),dp[i][j]:表示有i位不超过j的有多少个。
PS:开始傻逼的用dp[i][j]表示有i位前面的一共占了多少,这样的话只对特定的样例有点减枝,对所有样例没有减枝,思维转的不灵活。
代码:
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #define eps 1e-6 #define INF 0x3fffffff #define PI acos(-1.0) #define ll __int64 #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; int a,b; int sa[22]; int bit[30],num; int lim; int Cal(int aa) { int res=0; int cnt=0; while(aa) { res+=(aa%10)*sa[cnt]; //求F(A) cnt++; aa/=10; } return res; } int dp[22][11000]; ll dfs(int cur,int la,int flag) { if(!cur) { if(!flag) dp[cur][la]=1; return 1; } if(dp[cur][la]!=-1&&!flag) //记忆话搜索 return dp[cur][la]; int Max=flag?bit[cur]:9; ll res=0; for(int i=0;i<=Max;i++) { if(la<i*sa[cur-1]) continue; res+=dfs(cur-1,la-i*sa[cur-1],flag&&(i==Max)); } if(!flag) dp[cur][la]=res; return res; } ll init(int x) { num=0; while(x) { bit[++num]=x%10; //分离出每一位(十进制) x/=10; } return dfs(num,lim,1); } int main() { int t; sa[0]=1; for(int i=1;i<=10;i++) //sa[i]=2^i sa[i]=sa[i-1]*2; scanf("%d",&t); memset(dp,-1,sizeof(dp)); for(int ca=1;ca<=t;ca++) { scanf("%d%d",&a,&b); lim=Cal(a); //求出F(A) printf("Case #%d: %d\n",ca,init(b)); } return 0; }