ICPC 2022 网络赛 d ( 数位dp + 二分

#include
using namespace std;
using VI = vector;
using ll = long long;
const int mod = 998244353;

ll n;
int d[100];
int dp[60][40][40][2];
set s;
//枚举数位,枚举这一位余数是几
//每一位的限制,
int dfs(int pos , int ct1 , int h0 , int lead0 , int limit){
    if(pos == -1){
        if(ct1 == h0 && ct1) return 1;
        else return 0;
    }
    auto x = dp[pos][ct1][h0][lead0];
    if(x != -1 && !limit) return x;
    
    x = 0;
    int up = limit ? d[pos] : 1;
    for(int i = 0 ; i <= up ; i++){
        int t = ct1 + (i == 1);
        int h;
        if(!lead0 && i == 0) h = h0 + 1;
        else h = 0;
        x += dfs(pos - 1 , t , h , lead0 && i == 0 , limit && i == up); 

    }
    if(!limit) dp[pos][ct1][h0][lead0] = x;
    return x;



}
int work(int x){
    int idx = -1;
    while(x){
        d[++idx] = x % 2;
        x/=2;
    }
    //memset(dp , -1 , sizeof dp);
    return dfs(idx , 0 , 0 ,1, 1);
}



void solve(){
    int l,r;
    cin>>l>>r;
    if(s.size()){

        int t = * s.lower_bound(l);
        if(t >= l && t <= r){
            cout<> 1;
        if(work(mid) - ct > 0){
            r = mid;
        }else{
            l = mid + 1;
        }
    }
    cout<>t;
    while(t--){
        solve();
    } 
}

考虑到各个数的状态 , 可能会存在一些共同的,因此不一定每次都要memset

每个数的limit状态不一定相同 , 把这个作为搜索的内容,其他的都可以设计再dp状态里面 

你可能感兴趣的:(dp,深度优先,算法)