3 0 100 1 10 5 100
Case #1: 1 Case #2: 2 Case #3: 13
题意:设n是十进制数x的位数,F(x) = An * 2^(n-1) + An-1 * 2^(n-2) + ... + A2 * 2 + A1 * 1.让你算出0~B中F(y)小于等于F(A)的数的个数。
思路:一开始用dp[i][num][jieguo]表示前i位总和为num,要求的数为jieguo的方案数,但是这样就爆内存了。所以用dp[i][num]表示算到前i位,剩余num,且后面算下去结果大于等于0的方案数,这样就可以转移了。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<bitset> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) int dp[11][6000]; int a,b,jieguo; int wei[12]; int po[20]={1,2,4,8,16,32,64,128,256,512,1024,2048}; int get(int state) { int i,j; int shu[12],len=0,sum=0; while(state){ shu[len]=state%10; sum+=shu[len]*po[len]; len++; state/=10; } return sum; } int dfs(int pos,int num,int lim,int zero) { int i,j; if(num<0)return 0; if(pos==-1){ if(num>=0)return 1; return 0; } if(lim==0 && dp[pos][num]!=-1 ){ return dp[pos][num]; } int ed=lim?wei[pos]:9; int ans=0,num1; for(i=0;i<=ed;i++){ if(zero&&i==0){ num1=num; } else{ num1=num-po[pos]*i; } ans+=dfs(pos-1,num1,lim&&i==ed,zero&&i==0 ); } if(lim==0){ dp[pos][num]=ans; } return ans; } int solve(int x) { int i,j,tot=0; while(x){ wei[tot++]=x%10; x/=10; } return dfs(tot-1,jieguo,1,1); } int main() { int n,m,i,j,T,cas=0; memset(dp,-1,sizeof(dp)); scanf("%d",&T); while(T--) { scanf("%d%d",&a,&b); jieguo=get(a); cas++; printf("Case #%d: %d\n",cas,solve(b)); } return 0; }