ZOJ 4126 Digit Mode

题目链接:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370521

用类似数位dp的思想去枚举每个状态,记录每个数字的出现次数,当后面的数组可以任意填时,就枚举答案,枚举每个数字的在后面的出现次数,做背包转移。有个细节是要考虑前导零。

设数字的长度为n,复杂度大概是n*10*O(dp转移的复杂度),n^4*10^3 ,实际上还要除一些常数,感觉大概可以过。

所以先写了一发,剪枝也一直T的代码。

后面把9,99,999...这样的数字的答案打表预处理,就不用考虑前导0的情况,复杂度大概能除2,不做剪枝大概也可以过....

#include
#define debug(x) cerr<<#x<<" = "<<(x)<=ti[x])x=i;
        ans+=x;
        return;
    }
    if(!flag){
        int ma=0,N=pos;
        for(int i=0;i<=9;i++)ma=max(ma,ti[i]),N+=ti[i];
        for(int x=1;x<=9;x++){
            for(int y=0;y<=pos;y++){
                if(ti[x]+y0||(x>s;
    n=s.size();
    ans=tbl[n-1];
    for(int i=1;i<=n;i++)a[i]=s[n-i]-'0';
    for(int i=1;i<=a[n];i++){
        ti[i]++;
        dfs(n-1,i==a[n]);
        ti[i]--;
    }
    cout<>T;
    while(T--){
        solve();
    }
    return 0;
}

 

你可能感兴趣的:(ZOJ 4126 Digit Mode)