• HDU 4352 XHXJ's LIS


    传送门

    题目大意:

    求[l, r]中数位的最长上升序列恰好为k的数的个数。

    题目分析:

    首先要理解(o(nlogn))求LIS问题的思路,每次寻找第一个大于等于的数将其更改。
    设dp[pos][sta][k]表示第pos位,sta见后,加入k是为了初始化减少后面的时间。
    sta表示前pos位的LIS,是一个2进制数,110位表示09是否被选,比如现在状态是0010100000,就是说LIS是2,4,分两种情况:

    • 现在加入一个数字3,用LIS的方法找到第一个大于等于3的数----4,将其置为0,并把3置为1,sat变为0011000000.
    • 若加入6,没有大于等于它的数,就直接将6置为1,sat变为0010101000
      需要先预处理to[i][j]表示i状态加入数字j后转移到的状态来加速。 我卡了半天T所以必须初始化。

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    struct ioSys{
        inline ll read(){
            ll i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar())
                i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline void wr(int x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wr(x / 10);
            putchar(x % 10 + '0');
        }
        inline void operator >> (ll &x){
            x = read();
        }
        inline void operator << (int x){
            wr(x);
        }
    }IO;
    
    ll T;
    ll l, r, k, len;
    typedef long long ll;
    ll dp[25][1050][15], s[25], to[1050][15], oneNum[1050];
    
    inline void convert(ll x){
        len = 0;
        memset(s, 0, sizeof s);
        while(x) s[++len] = x % 10, x /= 10;
    }
    
    inline ll count(ll x){
        int ret = 0;
        while(x) ret++, x = x & (x - 1);
        return ret;
    }
    
    inline void init(){
        memset(dp, -1, sizeof dp);
        for(int i = 0; i <= (1 << 10) - 1; i++){
            for(int j = 0; j <= 9; j++){
                int  tmp = 0, p;
                for(p = j; p < 10; p++)
                    if(i & (1 << p)) break;
                if(p == 10) tmp = i | (1 << j);
                else tmp = i ^ (1 << p) | (1 << j);
                to[i][j] = tmp;
            }
        }
        for(int i = 0; i <= (1 << 10) - 1; i++)
            oneNum[i] = count(i);
    }
    
    inline ll DP(int pos, int sta, bool limit, bool lead, int K){
        if(!limit && !lead && dp[pos][sta][K] != -1) return dp[pos][sta][K];
        if(pos == 0) return oneNum[sta] == k || (lead && K == 1);
        int high = limit ? s[pos] : 9;
        ll ret = 0;
        for(int i = 0; i <= high; i++){
            if(i == 0 && lead) ret += DP(pos - 1, 0, limit && (i == high), true, K);
            else
                ret += DP(pos - 1, to[sta][i], limit && (i == high), false, K);
        }
        if(!limit && !lead) dp[pos][sta][K] = ret;
        return ret;
    }
    
    int main(){
       T = IO.read();
       init();
       for(int t = 1; t <= T; t++){
           IO >> l, IO >> r, IO >> k;
           convert(r);
           ll ret1 = DP(len, 0, 1, 1, k);
           convert(l - 1);
           ll ret2 = DP(len, 0, 1, 1, k);
           printf("Case #%d: %I64d
    ", t, ret1 - ret2);
       }
       return 0;
    }
    
    
  • 相关阅读:
    ffmpeg合并视频+音频
    You-Get和youtube-dl
    【会声会影】初装会声会影时,必要的设置
    【会声会影】视频导出、输出时,如何设置参数
    【会声会影】导入的srt字幕文件,如何快速批量调整字体及大小
    把h264文件快速包装成mp4格式
    Notepad++正则表达式——去掉srt字幕文件的时间轴
    百度地图API的网页使用
    ASPCMS_判断语句if标签的使用
    Grid布局
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7662090.html
Copyright © 2020-2023  润新知