题目链接
3 0 100 1 10 5 100
Case #1: 1 Case #2: 2 Case #3: 13
题解:F(x)的最大值不超过5000,可以用数位dp来做。
用dp[i][j]表示0到i位还没有填(即不超过i位的所有数字中),要让F值小于等于等于j的方案数。
dp[i][j]+=dp[i-1][j-x*(1<<i)], 0<=x<=9;
数位统计问题的具体统计方法可以参加相关数位dp的论文。
代码如下:
#include<cstdio> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<iostream> #include<map> #include<vector> #include<algorithm> #include<set> #include<cmath> using namespace std; const int nn = 3100; const int inf = 0x3fffffff; int A,B; int wei[20]; int dp[20][5000]; int F(int x) { int re=0; int ix=0; while(x) { if(x%10) re+=x%10*(1<<ix); x/=10; ix++; } return re; } int dfs(int id,int lim,bool man) { if(lim<0) return 0; if(id==-1) { return 1; } if(!man&&dp[id][lim]!=-1) return dp[id][lim]; int re=0; int en=man?wei[id]:9; for(int i=0;i<=en;i++) { re+=dfs(id-1,lim-i*(1<<(id)),man&&(i==en)); } if(!man) dp[id][lim]=re; return re; } int solve() { int ix=0; memset(wei,0,sizeof(wei)); while(B) { if(B%10) { wei[ix]=B%10; } ix++; B/=10; } return dfs(10,F(A),true); } int main() { memset(dp,-1,sizeof(dp)); int t,cas=1; scanf("%d",&t); while(t--) { scanf("%d%d",&A,&B); printf("Case #%d: %d\n",cas++,solve()); } return 0; }