求助,关于数位dp
查看原帖
求助,关于数位dp
265453
strange757楼主2022/6/15 17:57

rt,对于本题,这么写就可以过

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
int q, b, l, r;
int f[11][70][1024], a[1024];
//第一位表示进制,第二位表示位数,第三位表示是否符合条件
int dfs(int x, int now, int z, int up){
    if(!x) return !now;
    if(!z && !up &&f[b][x][now] != -1) return f[b][x][now];
    int l, sum  = 0;
    if(up) l = a[x];
    else l = b - 1;
    for(int j = 0; j <= l; j++){
        sum += dfs(x - 1, (z&&!j)?0:(now^(1<<j)), z&&!j, up&&(j == l));
    } 
    if(!z && !up)f[b][x][now] = sum;
    return sum;
}
int query(int x){
    int len = 0, k = x;
    while(k){
        a[++len] = k % b;
        k/=b;
    }
    return dfs(len, 0, 1, 1);
}
signed main(){
    scanf("%lld", &q);
    memset(f, -1, sizeof(f));
    while(q--){
        scanf("%lld%lld%lld", &b, &l, &r);
        printf("%lld\n", query(r) - query(l - 1));
    }
    return 0;
}

但是按照我一般的习惯写会挂掉,其他数位dp这么写一般不会出错。

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
int q, b, l, r;
int f[11][70][1024][2][2], a[1024];
//第一位表示进制,第二位表示位数,第三位表示是否符合条件
int dfs(int x, int now, int z, int up){
    if(!x) return !now;
    if(f[b][x][now][z][up] != -1) return f[b][x][now][z][up];
    int l, sum  = 0;
    if(up) l = a[x];
    else l = b - 1;
    for(int j = 0; j <= l; j++){
        sum += dfs(x - 1, (z&&!j)?0:(now^(1<<j)), z&&!j, up&&(j == l));
    } 
    f[b][x][now][z][up] = sum;
    return sum;
}
int query(int x){
    int len = 0, k = x;
    while(k){
        a[++len] = k % b;
        k/=b;
    }
    return dfs(len, 0, 1, 1);
}
signed main(){
    scanf("%lld", &q);
    memset(f, -1, sizeof(f));
    while(q--){
        scanf("%lld%lld%lld", &b, &l, &r);
        printf("%lld\n", query(r) - query(l - 1));
    }
    return 0;
}
2022/6/15 17:57
加载中...