ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

XHXJ's LIS HDU - 4352 数位dp

2020-03-16 10:07:22  阅读:255  来源: 互联网

标签:HDU sta XHXJ int ll pos dp 4352 数字


参考博客:https://www.cnblogs.com/ZGQblogs/p/10679934.html

//dp[pos][sta][k]
//搜索到第几位,之前的最长上升子序列的状态,就是输入的那个k
//sta的二进制每一位,都对应了数位上的一个数字
//举例来说:如果sta按照数字13425来更新。
//首先遇到1,变成0100000000(或者0000000010,其实这是完全一样的,只要保证不同状态的sta不一样就行了)
//然后遇到3,很明显,之前没有比3更大的数字,然后变成0101000000
//遇到4,sta变成0101100000
//不难看出,sta中1的个数,就是LIS的长度
//然后遇到2,这时大于等于2的有一个3.于是把3的二进制1交给2,sta变成0110100000
//为什么这么做?????
//首先我们知道,这样做绝不会改变1的个数,如果之前出现过2
//那么sta就不会变化,否则就把之后最近的那个1挪到当前位置
//然后再看这4个数字:1342
//如果之后出现的数字有比这四个数字都大的,那么之前究竟是1243还是1342都对后方的更新没有影响了
//就如同例子中的5,它只需知道,在之前出现的数字中最大的没有自己大就行了,因为只要这样,就可把5位置的0变成1
//注意:如果有多种状态,( 1243 ,1342 ),只要对后续影响相同,就可以看做同一种状态
//如果之后出现的数字没有比这四个数都大的,那么还是不会改变1的个数
//但是,出现数字2的时候,第二个1向前挪了一位,这实际上是把LIS为2的序列由13变成了12,这里对后续的影响是不同的
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int digit[30];
ll dp[30][1<<10][12];
int Update(int state,int bit){
    for(int i = bit; i <= 9; i++){
        if(state & (1 << i)){
            state ^= (1 << i);
            break;
        }
    }
    return state | (1 << bit);
}
int Getlen(int state){
    int cnt = 0;
    while(state){
        cnt += (state & 1);
        state >>= 1;
    }
    return cnt;
}
//                      前导0     上界 
ll dfs(int pos,int state,int lead,int limit,int k){
    if(pos == -1)
        return Getlen(state) == k;
    ll &dpnow = dp[pos][state][k];
    if(!limit && dpnow != -1)
        return dpnow;
    int max_digit = limit ? digit[pos] : 9;
    ll ans = 0;
    for(int i = 0; i <= max_digit; i++){
        ans += dfs((pos - 1), (lead && i == 0 ? 0 : Update(state,i)), (lead && i == 0), (limit && i == max_digit), k);
    }
    if(!limit)
        dpnow = ans;
    return ans;
}
 
ll solve(ll n,int k){
    int pos = 0;
    while(n){
        digit[pos++] = n % 10;
        n /= 10;
    }
    return dfs(pos-1,0,1,1,k);
}
int main(){
    int T,cas = 0;
    cin >> T;
    memset(dp,-1,sizeof(dp));
    while(T--){
        ll l,r;
        int k;
        cin >> l >> r >> k;
        cout << "Case #" << ++cas << ": ";
        cout << solve(r,k) - solve(l-1,k) << endl;
    }
    return 0;
}

标签:HDU,sta,XHXJ,int,ll,pos,dp,4352,数字
来源: https://www.cnblogs.com/QingyuYYYYY/p/12502026.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有