标签:数位dp
题意:定义 F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1(其中 x = AnAn-1An-2 ... A2A1),那么给定A,B,求[0,B]区间的i,满足F(i)<=F(A)
的个数。
思路:设dp[ pos ] [ k ]为当前考虑pos位,之后(pos + 1)位与之前的位数组合形成的F函数值不超过k的数的个数,详见代码:
/********************************************************* file name: hdu4734.cpp author : kereo create time: 2015年01月20日 星期二 11时09分03秒 *********************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<map> #include<vector> #include<stack> #include<cmath> #include<string> using namespace std; typedef long long ll; const int sigma_size=26; const int N=10; const int MAXN=6000+50; const int inf=0x3fffffff; const double eps=1e-8; const int mod=100000000+7; #define L(x) (x<<1) #define R(x) (x<<1|1) #define PII pair<int, int> #define mk(x,y) make_pair((x),(y)) int res; int bit[N],dp[N][MAXN],a[N],p[N]; int dfs(int pos,int st,int flag){ if(pos == -1) return 1; if(flag && dp[pos][st]!=-1) return dp[pos][st]; int ans=0; int x=flag ? 9 : bit[pos]; for(int i=0;i<=x;i++){ int k=st-(int)p[pos]*i; if(k<0) continue; ans+=dfs(pos-1,k,flag || i<x); } if(flag) dp[pos][st]=ans; return ans; } int solve(int x){ int len=0; do{ bit[len++]=x%10; x/=10; }while(x); return dfs(len-1,res,0); } int main(){ int T,kase=0; scanf("%d",&T); p[0]=1; for(int i=1;i<10;i++) p[i]=p[i-1]*2; memset(dp,-1,sizeof(dp)); while(T--){ int A,n; scanf("%d%d",&A,&n); int cnt=0; res=0; do{ a[cnt++]=A%10; A/=10; res+=p[cnt-1]*a[cnt-1]; }while(A); int ans=solve(n); printf("Case #%d: %d\n",++kase,ans); } return 0; }
标签:数位dp
原文地址:http://blog.csdn.net/u011645923/article/details/43094941