思路:
这个数位卡我时间又卡我空间,时间和空间限制都很小,时间就500ms。
图片说明

我想通过再开一个数组记录访问过的状态是否与本次输入有关,来避免每次都要初始化数组,同时又不用多开一维(会爆空间,),即便如此还是会超时,因为它有组数据,所以如果每次都重新算一遍的话,铁定超时,与是否初始化的时间开销无关。

然后参考了一位博主的博客,我数位白学了。

对于我解这题固有的思路而言,"判断是否"并没有体现在的状态中,所以这样产生的值是依赖于的,仅能应用在当前数据上,如果数据量大就会

但是完全可以采取更优的方案消除状态与输入的相关性。(无论你取什么值,都是一个常量,永远不会改变。)
以前也有过消除状态与输入的相关性,但都是模板刚好就能完成或者没有多组输入,而这题的第二维需要存储第位到最低位最多还能够增加的值,留意当状态与输入相关时怎么去消除这个性质。

我居然因为没有初始化卡了几十分钟,菜~

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include <vector>
#include<map>
#include<set>
#include<utility>
using namespace std;
typedef long long ll;
inline ll read() {
    ll s = 0, w = 1;
    char ch = getchar();
    while (ch < 48 || ch > 57) {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= 48 && ch <= 57)
        s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}
int dp[11][4600];
int digit[11],all;
int dfs(int len,int sum,bool limit) {
    if(sum<0) return 0;
    if(!len) {
        return 1;
    }
    if(!limit&&dp[len][sum]!=-1) return dp[len][sum];
    int endi=(limit?digit[len]:9);
    int ans=0;
    for(int i=0;i<=endi;++i) {
        ans+=dfs(len-1,sum-i*(1<<(len-1)),limit&&i==endi);
    }
    if(!limit) dp[len][sum]=ans;
    return ans;
}
int solve(ll x) {
    int len=0;
    while(x) {
        digit[++len]=x%10;
        x/=10;
    }
    return dfs(len,all,true);
}
void change(int n) {
    all=0;
    int tmp=1;
    while(n) {
        all+=(n%10)*tmp;
        tmp<<=1;
        n/=10;
    }
}
int main() {
    int t=read(),cas=0,r,n;
    memset(dp,-1,sizeof dp);
    while(t--) {
        cas+=1;
        n=read(),r=read();
        change(n);
        printf("Case #%d: %d\n",cas,solve(r));
    }
    return 0;
}